Skip to main content

FC MCP Server

An MCP server, built on FastMCP, that exposes FC operations as MCP tools. Under the hood every tool shells out to fc-client, so an AI agent can lock/unlock resources, query status, run console/ssh/power commands, and drive image deploy/flash workflows.

Architecture

The server is plugin based. mcp_server.py creates the FastMCP instance, loads the internal plugin, then auto-discovers external plugins.

fc_mcp/
  mcp_server.py                # entry point (fc-mcp), transport handling
  mcp_base.py                  # MCPPlugin base class + shared helpers
  mcp_plugins/
    internal/fc_mcp.py         # core fc-client operations (always loaded)
    external/
      uuu_bcu_mcp.py           # UUU/BCU flashing tools (sample external plugin)
      uboot_mcp.py             # U-Boot console deploy tools: predeploy / uri / livedeploy (sample)
      deploy_recommender_mcp.py# deploy method recommender (entry point)

Any *_mcp.py file placed under mcp_plugins/external/ that exposes a Plugin class is discovered and loaded automatically at startup.

Installation

From the repository root:

python setup.py install fc-mcp

This installs the fc-mcp console entry point. Requires Python >= 3.10 and fastmcp >= 2.3 (needed for the Streamable HTTP transport).

Starting the server

The server supports two transports. stdio is the default and is what a local client (for example fc-agent, which launches the server as a subprocess) uses. Streamable HTTP runs the server as a standalone HTTP service so remote / third-party MCP clients can connect.

stdio (default)

fc-mcp

The client is responsible for spawning the process and talking JSON-RPC over stdin/stdout.

Streamable HTTP

# Local only (default host 127.0.0.1, port 8000, path /mcp)
fc-mcp --transport http

# Expose to the network
fc-mcp --transport http --host 0.0.0.0 --port 8000 --path /mcp

Clients then connect to http://<host>:<port><path>, e.g. http://127.0.0.1:8000/mcp.

Options

Every flag has a matching environment variable, so the server can be configured in containers/services without CLI arguments. CLI flags take precedence.

Flag Environment variable Default Description
--transport FC_MCP_TRANSPORT stdio Transport mode: stdio or http.
--host FC_MCP_HOST 127.0.0.1 Bind host (HTTP transport only).
--port FC_MCP_PORT 8000 Bind port (HTTP transport only).
--path FC_MCP_PATH /mcp URL path the MCP endpoint is served on (HTTP only).
--workdir FC_MCP_WORKDIR (unset) Working directory for the server. Created automatically if missing. Supports ~/$VAR.
(none) FC_MCP_AUTH_TOKEN (unset) Static Bearer token for HTTP transport (env only).

Example using environment variables:

export FC_MCP_TRANSPORT=http
export FC_MCP_HOST=0.0.0.0
export FC_MCP_PORT=9000
fc-mcp
# -> http://0.0.0.0:9000/mcp

Working directory

By default the server runs in whatever directory the launching process is in (for stdio this is the MCP client's working directory). Set FC_MCP_WORKDIR to force a specific working directory. This is where generated artifacts (for example flash/U-Boot helper scripts) are written.

  • The directory is created automatically (including parent directories) if it does not exist.
  • ~ and $VAR are expanded, so a shared config works per user. For shell configs prefer $HOME/... (the shell expands it at assignment); the server also expands ~/$VAR itself as a fallback, so both resolve to the running user's home directory.
  • If the directory cannot be created or entered (permissions, path is a file), a warning is printed and the current directory is kept, so startup is never blocked.
# Any of these resolve to the running user's home-based directory:
export FC_MCP_WORKDIR="$HOME/fc_mcp_work"   # recommended (shell expands $HOME)
export FC_MCP_WORKDIR="~/fc_mcp_work"        # expanded by the server
fc-mcp

Authentication (HTTP transport)

By default the HTTP endpoint is unauthenticated — anyone who can reach http://<host>:<port><path> can invoke every tool. When exposing the server on a network (--host 0.0.0.0), enable static Bearer-token auth by setting the FC_MCP_AUTH_TOKEN environment variable:

export FC_MCP_TRANSPORT=http
export FC_MCP_HOST=0.0.0.0
export FC_MCP_AUTH_TOKEN="$(openssl rand -hex 32)"
fc-mcp

Behavior:

  • If FC_MCP_AUTH_TOKEN is unset or empty, the server runs without auth (backward compatible).
  • If set, every request must include Authorization: Bearer <token>; otherwise the server responds with 401 Unauthorized.
  • The token is only enforced for HTTP transport. stdio transport ignores it.

The token is intentionally read only from an environment variable, not from a CLI flag: command-line arguments are visible to other local users via ps / /proc/<pid>/cmdline (and leak into shell history), whereas /proc/<pid>/environ is readable only by the process owner and root.

Client config with a Bearer token:

{
  "mcpServers": {
    "fc": {
      "url": "http://127.0.0.1:8000/mcp",
      "headers": {
        "Authorization": "Bearer <token>"
      }
    }
  }
}

Connecting a third-party MCP client

For HTTP transport, point the client at the server URL. A typical MCP client config entry looks like:

{
  "mcpServers": {
    "fc": {
      "url": "http://127.0.0.1:8000/mcp"
    }
  }
}

For stdio transport, configure the client to launch the process instead:

{
  "mcpServers": {
    "fc": {
      "command": "fc-mcp"
    }
  }
}

Available tools

Grouped by purpose (see the plugin sources for full signatures):

  • Resource management (mcp_plugins/internal/fc_mcp.py): lock, unlock, status, cluster_info, all_locks, advanced_features, get_console_names, set_comment.
  • Command execution (mcp_plugins/internal/fc_mcp.py): get_fc_command (build a command string), fc_command (run or return ssh/console/power/scp/rsync commands).
  • Deploy recommender (mcp_plugins/external/deploy_recommender_mcp.py): recommend_deploy_method — the ENTRY POINT for any deploy/burn/flash request.
  • Deploy / flash (mcp_plugins/external/uuu_bcu_mcp.py): boot_mode_switch, flash_usb_boot_nexus, flash_usb_boot_uri, flash_non_usb_boot_uri.
  • U-Boot console deploy (mcp_plugins/external/uboot_mcp.py): get_board_server_ip, get_uboot_config_uri, get_uboot_config_nexus, flash_livedeploy (universal fallback deploy, always available), list_available_boards.

Selecting single / cluster mode per call

The resource-management and command-execution tools accept two optional parameters, fc_server and lg_coordinator, that set fc-client's FC_SERVER / LG_COORDINATOR for that single call only:

  • pass BOTH -> single mode
  • otherwise -> cluster mode (fc-client falls back to cluster whenever the pair is incomplete; note a real cluster still needs FC_SERVER to connect)

Each call builds a fresh environment (inherited values are cleared first) and echoes the resulting mode in its result. There is no server-side state, so different chat windows can target different boardfarms without restarting the server: tell the agent once which boardfarm to use and it passes these params to every subsequent call.

Commands and scripts the server emits for external execution carry the same target so they do not silently fall back to the default (cluster) boardfarm:

  • Interactive ssh / console commands and the long-running scp / rsync manual command returned by fc_command, as well as the command string built by get_fc_command, are prefixed inline (FC_SERVER='...' LG_COORDINATOR='...' fc-client ...).
  • Generated deploy scripts (uuu / predeploy / livedeploy) get an export block pinned at the top of the script, so every fc-client invocation inside the script targets the boardfarm the MCP call resolved.

The deploy tools (flash_usb_boot_nexus, flash_usb_boot_uri, flash_non_usb_boot_uri, get_uboot_config_nexus, flash_livedeploy, boot_mode_switch) accept fc_server / lg_coordinator, and recommend_deploy_method threads them into recommended.next_tool_args so the agent forwards them automatically. When neither is set, no prefix or export block is added (default cluster behavior).

Deploy workflow

There are three deploy methods, all of which generate an executable script (returned as script_path) that doubles as an execution record:

Method boot_device boot_target Requires Next tool(s)
predeploy sd boot nfs has_predeploy get_uboot_config_nexus / get_uboot_config_uri
uuu usb boot nfs / mmc has_uuu flash_usb_boot_nexus / flash_usb_boot_uri / flash_non_usb_boot_uri
livedeploy sd boot nfs always flash_livedeploy

The individual deploy tools are low-level executors. Do NOT call them directly. Instead follow this deterministic workflow:

  1. Call advanced_features to get has_predeploy / has_uuu.
  2. Call recommend_deploy_method with those capabilities plus the user-provided params (Nexus release_build_plan + build_number for coarse-grained, OR *_uri for fine-grained).
  3. Call ONLY the tool named in recommended.next_tool, using recommended.next_tool_args.

Decision matrix

Coarse-grained (Nexus build specified):

Capability Default Alternatives
predeploy only predeploy livedeploy
uuu only uuu livedeploy
neither livedeploy
both predeploy uuu, livedeploy

Fine-grained (URIs specified):

Capability Default Alternatives
predeploy only livedeploy — (predeploy can't take URIs)
uuu only uuu uuu (mmc), livedeploy
neither livedeploy
both uuu livedeploy

Extending with plugins

Add a new *_mcp.py file under mcp_plugins/external/ that defines a Plugin class subclassing MCPPlugin and implementing register_tools():

from fc_mcp.mcp_base import MCPPlugin


class Plugin(MCPPlugin):
    def register_tools(self):
        @self.mcp.tool()
        def my_tool(resource_id: str) -> dict:
            """Describe what the tool does for the agent."""
            ...
            return {"success": True}

The file is picked up automatically the next time the server starts.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

fc_mcp-0.9.8.tar.gz (222.1 kB view details)

Uploaded Source

File details

Details for the file fc_mcp-0.9.8.tar.gz.

File metadata

  • Download URL: fc_mcp-0.9.8.tar.gz
  • Upload date:
  • Size: 222.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.2

File hashes

Hashes for fc_mcp-0.9.8.tar.gz
Algorithm Hash digest
SHA256 a2353600cf85d4bd5699a175d6be2847b535f14b72c06e83699db9418bb39269
MD5 21a89ca7c6f51f9c4966a707a5ba4e32
BLAKE2b-256 9975d5bbd5b41213c58e1f44355da9769e4308bc42def5b7897ae0bcc2677d8d

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.9.8 This release

1 file

0.9.7

1 file

0.9.6

1 file

0.9.5

1 file

0.9.4

1 file

0.9.3

1 file

0.9.2

1 file

0.9.1

1 file

0.9.0

1 file

0.8.16

1 file

0.8.15

1 file

0.8.14

1 file

0.8.13

1 file

0.8.12

1 file

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page