FsLangMCP
Health Warn
- License — License: MIT
- Description — Repository has a description
- Active repo — Last push 0 days ago
- Low visibility — Only 7 GitHub stars
Code Pass
- Code scan — Scanned 12 files during light audit, no dangerous patterns found
Permissions Pass
- Permissions — No dangerous permissions requested
No AI report is available for this listing yet.
Semantic F# for AI coding agents (Claude Code · Cursor · Copilot · Codex) — an MCP server that gives LLMs real FCS/FSAC compiler intelligence (find, check, types, rename) instead of grepping F#.
FsLangMCP (F# + FsMcp + FsAutoComplete + FCS)
FsLangMcp is an MCP server for AI coding agents working on F# projects. It combines fsautocomplete (LSP-shaped editor semantics) and FSharp.Compiler.Service (in-process compiler semantics) into a single stdio process designed for agent workflows. Start with find (one multi-project symbol search) and check (one trustworthy type-check verdict); the lower-level textDocument_* / workspace_* / fcs_* tools stay available when you need a specific knob. Responses are paginated, errors are returned as structured invalid_args envelopes, fcs_check_file invalidates stale caches after edits, fcs_validate_snippet compiles arbitrary F# against your project's references, and fcs_record_field_audit catches the record-construction sites that textual search misses.
See the Quickstart for the 60-second on-ramp.
Components
fsautocomplete(LSP bridge for editor-like features)FSharp.Compiler.Service(compiler-semantic features for AI workflows)
Work in progress: APIs and tool shapes may still change.
When to use FsLangMcp (vs alternatives)
- If your agent only needs editor-position queries (completion at cursor,
go-to-definition at cursor, hover-type at cursor),fsautocompletealone
via a thin MCP wrapper is sufficient. - If you need project-wide search, cache-aware reanalysis after edits,
snippet validation against the loaded project's NuGet references, or
paginated outlines that fit a 200k-token context — FsLangMcp adds the
agent-shaped surface that raw FSAC + raw FCS don't expose. - If you need raw FCS access (custom analyzer development, language-
server-side IDE integration), use FCS directly in your own process —
FsLangMcp is opinionated about response shapes for agents and doesn't
expose every FCS knob.
Quickstart
Install (.NET 10 required):
dotnet tool install -g FsLangMcp fslangmcp --bootstrap-tools # one-time: fetches fsautocomplete + ionide.projinfo.toolAdd to your MCP client config (Claude Code example — adjust for your client):
{ "mcpServers": { "fslangmcp": { "command": "fslangmcp" } } }Your first call: from the MCP client, call
set_projectwith your.fsprojpath:{ "projectPath": "/absolute/path/to/YourApp.fsproj" }You'll get back a response with
fslangmcpVersion,loadedProjects, andreadinessflags. Whenreadiness.lspistrue, you can call any other tool.Try a real tool: call
project_healthfor a fast preflight on the project:{ }(No args needed —
set_projectset the default.) The response tells you which compile files exist, which test projects were detected, and whether the LSP and FCS layers are ready.
That's it. From here you can browse the tool catalog for the right tool for your task, or skim troubleshooting when something looks off.
Changelog
See CHANGELOG.md for the full release history.
Response Shape
All tools return a consistent JSON envelope:
- Success:
{"status": "ok", "result": <payload>}(LSP tools) or{"status": "ok", ...fields}(FCS tools) - Not ready:
{"status": "not_ready", "message": "..."}— LSP workspace still loading - Invalid args:
{"status": "invalid_args", "message": "..."}— required string arg blank/missing onfcs_record_field_audit/fcs_project_symbol_uses/fcs_find_member_usages/fcs_find_symbol/fcs_referenced_symbols/fcs_nuget_types. Standardized in 0.8.2 (#120). - Error: MCP protocol error with
{"errorKind": "...", "message": "..."}payload
LSP positions (line, character) are 0-based.
What You Get
The textDocument_* and workspace_* tools are raw LSP/IDE-shaped proxies — useful for exact-position editor operations and FSAC debugging. Prefer the FCS tools and project_health for agent-friendly project understanding.
Primary entry points
Two tools cover the most common agent questions and should be your default. The twelve lower-level "cluster" tools below them are marked (prefer find) / (prefer check) — reach for them only when you need a specific knob these two don't expose. Full mechanics: docs/tools-detailed.md.
| Tool | What it does |
|---|---|
find |
Recommended for "where is X used?" Multi-project symbol search — sweeps every member .fsproj of the solution and unions definitions, references, record-field set sites, and member-usage sites, recovering cross-project sites the single-project search tools miss. Bare find(query) suffices; optional kind / scope narrow it. Supersedes the seven find-cluster tools. |
check |
Recommended for "did my edit compile?" One trustworthy verdict (clean / errors / unknown) from a FRESH in-process type-check, so it never reports a stale-{} false-clean and you don't fall back to dotnet build. Bare check() suffices; optional scope / path / snippet / speed. Supersedes the five check-cluster tools. |
LSP-proxy tools (FSAC-backed)
All require a prior set_project. Tagged [FSAC] in tool descriptions.
| Tool | What it does |
|---|---|
textDocument_completion |
Raw LSP proxy for completion at an exact position. |
textDocument_definition |
Raw LSP proxy for go-to-definition at an exact position. (prefer find) |
textDocument_references |
Raw LSP proxy for find-references at an exact position. For query-based agent workflows prefer fcs_project_symbol_uses / fcs_find_symbol. (prefer find) |
textDocument_formatting |
Raw LSP formatting proxy via Fantomas. Returns formatted text and edits; does not write to disk. |
textDocument_codeAction |
Raw LSP codeAction proxy at an exact position with empty diagnostic context. Useful for debugging FSAC. |
textDocument_rename |
Raw LSP semantic rename at an exact position. Returns raw WorkspaceEdit. |
workspace_symbol |
Quick lookup after set_project. IDE-shaped results without source context. (prefer find) |
workspace_diagnostics |
Cached LSP publishDiagnostics payload, scoped to one file or to the whole workspace. Optional path, fileGlob, severity filters. (prefer check) |
fsharp_signature_data |
Structured FSAC signature help via fsharp/signatureData at an exact call-site position. |
FCS in-process tools (compiler semantics)
Tagged [FCS in-process] in tool descriptions. Most accept an optional projectPath that falls back to the active set_project.
Which "check this code" tool should I use?
check— start here. One trustworthyverdict(clean/errors/unknown) from a FRESH in-process type-check; barecheck()covers the active project. The four tools below are its lower-level building blocks.fcs_parse_and_check_file— parse + typecheck one file, returns diagnostics. Cached.fcs_check_file— same as above, but invalidates the project's cached options + results first. Use whenworkspace_diagnosticslooks stale right after an Edit/Write.fsharp_compile— full projectParseAndCheckProject. Slowest but most thorough for project-wide validation. For absolute ground-truth across project boundaries,dotnet buildis still authoritative.
| Tool | What it does |
|---|---|
fcs_parse_and_check_file |
Parse + typecheck one file. Pass text for unsaved content. (prefer check) |
fcs_check_file |
Cache-invalidating parse + typecheck for one file. Surgically drops cached project-options + project-results entries for THIS project and calls InvalidateConfiguration before re-running. Use when workspace_diagnostics looks stale right after an Edit / Write. (prefer check) |
fcs_file_symbols |
Raw FCS symbol extraction for one file. includeAllUses adds locals / parameters / usages. Prefer fcs_file_outline for normal navigation. |
fcs_file_outline |
Compact per-file outline filtered to definitions: name, kind, range, signature/type, accessibility, declaration range. |
fcs_project_outline |
Compact project-wide outline over filtered compile files. Use maxFiles / maxResultsPerFile on large projects. |
fcs_project_symbol_uses |
Project-wide symbol-use search by symbol name / full name. Cached by resolved project options. (prefer find) |
fcs_find_symbol |
Project-wide search with grouped definitions / references and source line context. Better than chaining workspace_symbol + fcs_project_symbol_uses + shell line reads. Misses record-field-set construction sites — for those, use fcs_record_field_audit. (prefer find) |
fcs_find_member_usages |
Find all usage sites of a specific (typeName, memberName). FCS-resolved so dotted access, pipeline application, and overload resolution are handled correctly (unlike a textual rg). (prefer find) |
fcs_record_field_audit |
Find every construction site for a (typeName, fieldName) pair — both { Field = expr; ... } literal form and { x with Field = expr } update form. Closes the gap where fcs_find_symbol / textDocument_references look up the type name and miss field-set uses. (prefer find) |
fcs_symbol_at_word |
Tolerant FCS symbol lookup by line + word + occurrence. Prefer over exact-position hover/type queries. |
fcs_type_at_position |
Low-level exact-position FCS type/symbol query. Requires set_project (or explicit projectPath / projectOptions). Pass fuzzy=true to snap to nearest symbol within ±2 lines / ±5 cols. |
fcs_signature_help |
Exact-position FCS signature help around a call site. |
fcs_make_internal_visible |
Drops the private keyword from a let / module / type / member / val / new / static / abstract / override declaration at a given position. Returns a workspace edit; does NOT write the file. |
fcs_validate_snippet |
Compile an arbitrary F# snippet (.fs or .fsi mode) against the loaded project's references without modifying the project on disk. (prefer check) |
fcs_referenced_symbols |
Search across the project's referenced assemblies (NuGet + framework) for types whose DisplayName / FullName contains the query (case-insensitive). Reports assembly, kind, accessibility, isObsolete. |
fcs_nuget_types |
Enumerate types exported by one referenced assembly, matched by exact SimpleName (case-insensitive). Does NOT silently fall back to a less-specific assembly. To discover assembly names, use fcs_referenced_symbols first. |
fcs_get_project_options |
Get OtherOptions for a .fsproj via proj-info; use the result as projectOptions in other FCS tools. |
fsharp_compile |
FCS project validation. Loads .fsproj options through Ionide.ProjInfo, then runs FSharpChecker.ParseAndCheckProject. Does not run dotnet build, emit assemblies, or run tests. (prefer check) |
fsharp_project_inspect |
Read-only .fsproj inspection: compile order, references, source summary, and signature/implementation pairing. |
Meta / workflow tools
| Tool | What it does |
|---|---|
set_project |
[FSAC] Initialize or switch the FSAC/LSP project context. Must be called before textDocument_* and workspace_* tools. Accepts .fsproj, .sln, .slnx, or directory. Waits up to 30s for workspace load and clears FCS caches. |
project_health |
[FCS in-process] Fast read-only preflight: project options availability, source file readability, analyzer setup, test project discovery (isTestProject, testFrameworks, testCount, lastBuildSucceeded, lastBuildAt, binaryOutputPath), and current LSP readiness. Does not start FSAC, build, or test. |
fsharp_runtime_status |
[FCS in-process] Read-only observational snapshot: managed-heap sizes by generation/LOH/POH, GC counts, isServerGC, assembly load count, FCS checker config + project-results cache size, FSAC child-process working set. Numbers only — no interpretation. |
fslangmcp_version |
[meta] Zero-arg. Returns the installed FsLangMCP product version and name. Same value is surfaced in set_project.result.fslangmcpVersion and fsharp_runtime_status.fslangmcpVersion. Use when filing UX feedback. |
Notable response fields
set_project— response includesfslangmcpVersion(since 0.8.0, #115),loadedProjects: string[](.fsprojpaths discovered), andreadiness: { lsp, projectOptions, symbolIndex }flags (since 0.5.6, #106).workspace_diagnostics— single-file responses includeanalyzedAt; workspace-wide responses includemostRecentAnalyzedAtandanalyzedAtByUri(per-URIDateTimeOffsetmap). Since 0.8.0 (#116). WhenfileGlobis supplied,mostRecentAnalyzedAtis scoped to the glob-filtered subset (since 0.8.2, #123).fcs_find_symbol—projectDiagnosticsis scoped.projectDiagnosticsScope="matched-files"(normal) returns diagnostics only for files containing matches, with Info/Hint filtered out by default (setincludeInfo=trueto include).projectDiagnosticsScope="errors-only-no-matches"(zero-match case) surfaces error-severity diagnostics from the whole project so callers can detect broken projects. Since 0.8.0 / 0.8.1 (#114).fsharp_runtime_status— response includes top-levelfslangmcpVersion. Since 0.8.0 (#115).
Install As Dotnet Tool
Prerequisites: .NET SDK 10+ on PATH. fsautocomplete and ionide.projinfo.tool
are fetched automatically by --bootstrap-tools below.
From NuGet (recommended)
dotnet tool install -g FsLangMcp
fslangmcp --bootstrap-tools # one-time: fetches transitive F# tooling (fsautocomplete + ionide.projinfo.tool)
Update later with dotnet tool update -g FsLangMcp.
From source (developing FsLangMCP itself)
dotnet pack -c Release
dotnet tool install -g --add-source ./nupkg FsLangMcp
fslangmcp --bootstrap-tools # one-time: fetches transitive F# tooling
For local development of this repository, restore the local analyzer tool:
dotnet tool restore
After install, command is:
fslangmcp
If you'd rather install the transitive tools yourself instead of using--bootstrap-tools:
dotnet tool install -g fsautocomplete
dotnet tool install -g ionide.projinfo.tool
Runtime Options
Pass paths as command args (recommended):
--project <path-to-fsproj>or-p <path-to-fsproj>--fsac-command <cmd>(optional override)--fsac-args "<args>"(optional override)--bootstrap-tools(install/updatefsautocompleteandionide.projinfo.tool)
Environment fallbacks still work:
FSAC_COMMANDFSAC_ARGSFSA_PROJECT_PATH
Garbage collector — tuned for stdio servers
FsLangMCP ships with Workstation GC + Concurrent GC baked in via runtimeconfig.template.json. This is the recommended profile for stdio MCP servers per FsMcp's runtime tuning guide: an FCS workload is bursty (load → idle → next request), and Server GC's "don't release until OS pressure" produces alarming RSS growth on dev laptops that won't trigger pressure events.
Operators can override at the env-var level if needed (env always wins over runtimeconfig):
DOTNET_gcServer=1— opt back into Server GC (higher throughput, holds memory longer)DOTNET_GCHeapHardLimitPercent=0xA— cap heap at 10% of RAM (works with either GC mode)
MCP Stdio Config (Installed Tool)
{
"mcpServers": {
"fsharp": {
"command": "fslangmcp",
"args": ["--project", "/absolute/path/to/App.fsproj"],
"env": {
"FSAC_COMMAND": "fsautocomplete"
}
}
}
}
Parallel Agent Usage
For multiple agents sharing one FsLangMCP server, prefer the FCS tools and pass projectPath on every request:
{
"path": "/absolute/path/to/File.fs",
"projectPath": "/absolute/path/to/App.fsproj"
}
FCS tools resolve compiler options per project and cache project-wide results by the resolved .fsproj, so agents working on different projects do not share stale symbol caches. The server also limits expensive work by default:
FSLANGMCP_MAX_CONCURRENT_FCS=2FSLANGMCP_MAX_CONCURRENT_LSP=1
The LSP-proxy tools use one fsautocomplete workspace per server process. They are serialized to avoid corrupting the active document/workspace state, but they are not intended for independent parallel workspaces in the same MCP process.
Example Agent Session
Start by selecting a project:
{
"projectPath": "/absolute/path/to/App.fsproj",
"workspacePath": null,
"restartLsp": true
}
Then ask for a health report:
{
"projectPath": "/absolute/path/to/App.fsproj",
"workspacePath": null,
"scope": null,
"compileCheck": null
}
Typical next calls:
findwith aquerywhen you need every use of a symbol across the whole solution (the default "where is X used?" call).checkfor a singleclean/errors/unknownverdict after an edit (the default "did it compile?" call).fcs_parse_and_check_filewithprojectPathfor one file.fcs_file_outlinefor a compact map of a file.fcs_find_symbolwhen you need definitions/references plus source context.fcs_symbol_at_wordwhen you know the line and word but not the exact cursor column.fcs_project_symbol_useswithsymbolQueryfor project-wide references.workspace_diagnosticsto inspect current FSAC/compiler/analyzer diagnostics.fsharp_compilefor project-wide FCS parse+typecheck validation.
For repeated multi-agent use, pass projectPath directly to FCS tools instead of relying on mutable LSP workspace state.
Development Commands
just restore
just check
just analyze
just checkruns build + tests.just analyzeruns F# analyzers throughFSharp.Analyzers.Build.
The repository currently wires:
Ionide.AnalyzersG-Research.FSharp.AnalyzersFSharp.Analyzers.Build- local
fsharp-analyzerstool
MCP Stdio Config (Local Dev Without Install)
{
"mcpServers": {
"fsharp": {
"command": "dotnet",
"args": [
"run",
"--project",
"/path/to/FsLangMcp.fsproj",
"--",
"--project",
"/absolute/path/to/App.fsproj"
],
"env": {
"FSAC_COMMAND": "fsautocomplete"
}
}
}
}
How To Get projectOptions For FCS Tools
For accurate .fsproj / .sln / .slnx context, use ionide/proj-info:
dotnet tool install -g ionide.projinfo.tool
proj-info --project /absolute/path/to/App.fsproj --fcs --serialize
Use OtherOptions from the emitted JSON as projectOptions in:
fcs_parse_and_check_filefcs_file_symbolsfcs_project_symbol_uses
If both projectPath and projectOptions are omitted, the server first tries to auto-discover the nearest .fsproj. If no project can be found, it falls back to script-style inference (GetProjectOptionsFromScript), which is less accurate for large multi-project solutions.
set_project Tool
Use this MCP tool to switch active project context without restarting the MCP process.
Input shape:
{
"projectPath": "/absolute/path/to/App.fsproj",
"workspacePath": null,
"restartLsp": true
}
restartLsp defaults to true so the new context is applied immediately.
project_health Tool
Use project_health before deeper semantic work when you need to know whether FsLangMCP can trust the project state.
Input shape:
{
"projectPath": "/absolute/path/to/App.fsproj",
"workspacePath": null,
"scope": null,
"compileCheck": null
}
Notes:
- v0.3 expects an explicit
.fsprojpath or a directory with exactly one.fsproj. - Missing analyzers are reported as capability information, not as a health failure.
- Compile status is separate from tooling readiness.
project_healthdoes not run build or tests.
fsharp_compile Tool
Use fsharp_compile when you want read-only project-wide FCS validation without running dotnet build.
Input shape:
{
"projectPath": "/absolute/path/to/App.fsproj",
"workspacePath": null,
"timeoutMs": 60000
}
fsharp_compile returns a compact status, diagnostic counts, and FCS diagnostics. It uses FSharpChecker.ParseAndCheckProject, so it checks parse/typecheck errors across the project, but it does not execute the full MSBuild build pipeline, emit an assembly, or run tests.
Known Issues
- LSP proxy tools return
{"status": "not_ready"}if called beforefsautocompletehas finished loading the project.set_projectwaits up to 30 seconds — if you still getnot_ready, the project may be too large orfsautocompletemay have failed to start. project_healthv0.3 is intentionally project-focused. It does not yet inspect whole solutions or resolve ambiguous directories.- FCS tools fall back to script-style inference (
GetProjectOptionsFromScript) only when neitherprojectPathnor an auto-discovered.fsprojis available. In that mode, diagnostics and symbol data can be incomplete for multi-project solutions. fcs_project_symbol_usesresults are cached per project. Callset_projectto flush the cache when source files change on disk.
About Tool Dependencies
dotnet tool packages cannot automatically install other global tools during installation.
This project provides:
fslangmcp --bootstrap-tools
It runs dotnet tool update -g ... (or install if missing) for:
fsautocompleteionide.projinfo.tool
Reviews (0)
Sign in to leave a review.
Leave a reviewNo results found