sway/scripts/mdbook-forc-documenter
zees-dev 4c9c4c29bf
Some checks failed
CI / cargo-fmt-check (push) Has been cancelled
CI / check-forc-manifest-version (push) Has been cancelled
Codspeed Benchmarks / benchmarks (push) Has been cancelled
CI / check-dependency-version-formats (push) Has been cancelled
CI / get-fuel-core-version (push) Has been cancelled
CI / build-sway-lib-std (push) Has been cancelled
CI / build-sway-examples (push) Has been cancelled
CI / build-reference-examples (push) Has been cancelled
CI / forc-fmt-check-sway-lib-std (push) Has been cancelled
CI / forc-fmt-check-sway-examples (push) Has been cancelled
CI / forc-fmt-check-panic (push) Has been cancelled
CI / check-sdk-harness-test-suite-compatibility (push) Has been cancelled
CI / build-mdbook (push) Has been cancelled
CI / build-forc-doc-sway-lib-std (push) Has been cancelled
CI / build-forc-test-project (push) Has been cancelled
CI / cargo-build-workspace (push) Has been cancelled
CI / cargo-clippy (push) Has been cancelled
CI / cargo-toml-fmt-check (push) Has been cancelled
CI / cargo-run-e2e-test-evm (push) Has been cancelled
CI / cargo-test-lib-std (push) Has been cancelled
CI / forc-run-benchmarks (push) Has been cancelled
CI / forc-unit-tests (push) Has been cancelled
CI / forc-pkg-fuels-deps-check (push) Has been cancelled
CI / cargo-test-sway-lsp (push) Has been cancelled
CI / cargo-test-forc (push) Has been cancelled
CI / cargo-test-workspace (push) Has been cancelled
CI / cargo-unused-deps-check (push) Has been cancelled
CI / pre-publish-check (push) Has been cancelled
github pages / deploy (push) Has been cancelled
CI / cargo-run-e2e-test (push) Has been cancelled
CI / verifications-complete (push) Has been cancelled
CI / cargo-run-e2e-test-release (push) Has been cancelled
CI / cargo-test-forc-debug (push) Has been cancelled
CI / cargo-test-forc-client (push) Has been cancelled
CI / cargo-test-forc-mcp (push) Has been cancelled
CI / cargo-test-forc-node (push) Has been cancelled
CI / notify-slack-on-failure (push) Has been cancelled
CI / publish (push) Has been cancelled
CI / publish-sway-lib-std (push) Has been cancelled
CI / Build and upload forc binaries to release (push) Has been cancelled
feat: forc mcp server - with forc-call tool integration (#7284)
## Description

Introducing Forc-MCP module (CLI).

The MCP server can be run in 3 modes:
- `stdio`
- `sse`: long-running server - using http server-side-events
- `http`: long-running server - using http streams

### Forc-call integration

The first tool to be integrated is `forc-call` - which exposes the
following tool calls:
- `list_contract_functions`
- `transfer_assets`
- `get_execution_trace`
- `call_contract`

And the following resources:
- `MCP Type Encoding Reference`
- `MCP Tool Usage Examples`
- `Contract Examples with MCP Tools`

### Screenshots from `@modelcontextprotocol/inspector`

<img width="2543" height="549" alt="Screenshot 2025-07-15 at 5 09 16 PM"
src="https://github.com/user-attachments/assets/aaab5174-d5e6-4685-be71-fd17cd4f5d0f"
/>

<img width="2540" height="531" alt="Screenshot 2025-07-15 at 5 09 30 PM"
src="https://github.com/user-attachments/assets/9ab39d5a-950c-4404-a3a3-6e34b89f58e7"
/>

### Example usage (claude code)

Pre-requisites:
- Run local fuel-core node
    ```
fuel-core run --ip 127.0.0.1 --port 4000 --db-type rocks-db --debug
--historical-execution
    ```
- Deploy a contract to local node: `forc deploy --default-signer`


1. Run the MCP server (using http-steam in this example):
  ```
  cargo run -p forc-mcp -- http
  ```
2. Add mcp server to claude
  ```
claude mcp add --transport http forc-mcp-http http://localhost:3001/mcp
  ```
3. Use claude/LLM to interact with MCP server

<details>
<summary>Claude output</summary>

```
╭───────────────────────────────────────────────────╮
│ ✻ Welcome to Claude Code!                         │
│                                                   │
│   /help for help, /status for your current setup  │
│                                                   │
│   cwd: /Users/z/Desktop/fuellabs/sway             │
╰───────────────────────────────────────────────────╯


> Use the forc-mcp-http.

  Given the following sway contract:
  demo/demo/src/main.sw

  deployed at the following address:
  ae40e8dbe366c5ac61fe558e4e9139300534cd5d9463522621a903464c441eb2

  Using the forc-mcp-http:

  > list all its callable functions.
  > can you get the current count?
  > tell me how much gas it would cost to increment the count.
  > show me the execution trace for incrementing the count.
  ⎿  ⧉ Selected 14 lines from scratch/ai/templates.md in Cursor

⏺ I'll help you interact with the deployed Sway contract using forc-mcp-http. Let me start by reading
   the contract to understand its structure, then perform the requested operations.

⏺ Read(demo/demo/src/main.sw)
  ⎿  Read 34 lines (ctrl+r to expand)

⏺ Now I need to find the ABI file for this contract to use with the forc-mcp-http tools:

⏺ Search(pattern: "demo/demo/out/**/*.json")
  ⎿  Found 7 files (ctrl+r to expand)

⏺ Perfect! I found the ABI file and a deployment file that matches the contract address. Let me read
  the ABI:

⏺ Read(demo/demo/out/release/demo-abi.json)
  ⎿  Read 89 lines (ctrl+r to expand)

⏺ Now let me use the forc-mcp-http tools to interact with the contract. First, I'll list all callable
   functions:

⏺ forc-mcp-http:list_contract_functions (MCP)(abi: "/demo/demo/out/rele
                                             ase/demo-abi.json", contract_id: "ae40e8dbe366c5ac61fe55
                                             8e4e9139300534cd5d9463522621a903464c441eb2")
  ⎿ Callable functions for contract: ae40e8dbe366c5ac61fe558e4e9139300534cd5d9463522621a903464c441eb2

    get_count() -> u64
    … +186 lines (ctrl+r to expand)


⏺ Now let me get the current count:

⏺ forc-mcp-http:call_contract (MCP)(abi: "/demo/demo/out/release/demo-a
                                   bi.json", contract_id: "ae40e8dbe366c5ac61fe558e4e9139300534cd5d94
                                   63522621a903464c441eb2", function: "get_count")
  ⎿  {                                                                               
       "tx_hash": "0f1e868e75530f33d37748cac9ae25c33bf166c9e02d28e36f3ffdd67ecf3584",
       "total_gas": 65007,
     … +354 lines (ctrl+r to expand)

⏺ Now let me check the gas cost for incrementing the count using dry-run mode:

⏺ forc-mcp-http:call_contract (MCP)(abi: "/demo/demo/out/release/demo-a
                                   bi.json", contract_id: "ae40e8dbe366c5ac61fe558e4e9139300534cd5d94
                                   63522621a903464c441eb2", function: "increment_count",
                                   function_args: ["(1, 2)"], mode: "dry-run")
  ⎿  Error: Contract call failed: input must start with '{' and end with '}': (1, 2)

⏺ Let me fix the format for the struct argument:

⏺ forc-mcp-http:call_contract (MCP)(abi: "/demo/demo/out/release/demo-a
                                   bi.json", contract_id: "ae40e8dbe366c5ac61fe558e4e9139300534cd5d94
                                   63522621a903464c441eb2", function: "increment_count",
                                   function_args: ["{\"vals\": [1, 2]}"], mode: "dry-run")
  ⎿  Error: Contract call failed: input must start with '(' and end with ')': "vals": [1, 2]

⏺ Let me try the tuple format as shown in the example:

⏺ forc-mcp-http:call_contract (MCP)(abi: "/demo/demo/out/release/demo-a
                                   bi.json", contract_id: "ae40e8dbe366c5ac61fe558e4e9139300534cd5d94
                                   63522621a903464c441eb2", function: "increment_count",
                                   function_args: ["((1, 2))"], mode: "dry-run")
  ⎿  Error: Contract call failed: input must start with '{' and end with '}': ((1, 2))

⏺ Let me try with the correct struct format:

⏺ forc-mcp-http:call_contract (MCP)(abi: "/demo/demo/out/release/demo-a
                                   bi.json", contract_id: "ae40e8dbe366c5ac61fe558e4e9139300534cd5d94
                                   63522621a903464c441eb2", function: "increment_count",
                                   function_args: ["{(1, 2)}"], mode: "dry-run")
  ⎿  {                                                                               
       "tx_hash": "f694c73230e893b00968d8106f5bafbcd585c2cf0f4aea1c6a562ce7e1868690",
       "total_gas": 78940,
     … +399 lines (ctrl+r to expand)

⏺ Perfect! Now let me get the execution trace for that increment operation:

⏺ forc-mcp-http:get_execution_trace (MCP)(total_gas: 78940, trace_events: [{"Call":{"index":0,"method
                                         ":"increment_count","arguments":["Adder { vals: (1, 2)
                                         }"],"to":"ae40e8dbe366c5ac61fe558e4e9139300534cd5d9463522621
                                         a903464c441eb2","amount":0,"gas":26222}},{"LogData":{"index"
                                         :2,"id":"ae40e8dbe366c5ac61fe558e4e9139300534cd5d9463522621a
                                         903464c441eb2","value":"3","len":8}},{"ReturnData":{"index":
                                         4,"id":"ae40e8dbe366c5ac61fe558e4e9139300534cd5d9463522621a9
                                         03464c441eb2","data":"()"}},{"Return":{"index":6,"id":"00000
                                         00000000000000000000000000000000000000000000000000000000000"
                                         ,"val":1}},{"ScriptResult":{"index":7,"result":"Success","ga
                                         s_used":22210}}])
  ⎿  Traces:                                                                            
       [Script]
         ├─ [26222] 0xae40e8dbe366c5ac61fe558e4e9139300534cd5d9463522621a903464c441eb2::
     … +8 lines (ctrl+r to expand)

⏺ Summary

  Here are the results for the deployed Sway contract at
  ae40e8dbe366c5ac61fe558e4e9139300534cd5d9463522621a903464c441eb2:

  Callable Functions:

  1. get_count() → returns u64 (read-only)
  3. increment_count(adder: Adder) → returns () (read/write storage)

  Current Count:

  The current count is 1

  Gas Cost for Increment:

  Incrementing the count with Adder { vals: (1, 2) } costs 78,940 gas total (22,210 gas used by
  script)

  Execution Trace:

  The increment operation:
  - Calls increment_count with Adder { vals: (1, 2) }
  - Uses 26,222 gas for the contract call
  - Emits a log with value 3 (0 + 1 + 2 = 3, the new count)
  - Returns () (unit/void)
  - Total script gas used: 22,210
  - Result: Success

  The contract adds the two values from the Adder struct (1 + 2 = 3) to the current storage count (0)
   and logs the result.
```
</details>

## Checklist

- [ ] I have linked to any relevant issues.
- [ ] I have commented my code, particularly in hard-to-understand
areas.
- [ ] I have updated the documentation where relevant (API docs, the
reference, and the Sway book).
- [ ] If my change requires substantial documentation changes, I have
[requested support from the DevRel
team](https://github.com/FuelLabs/devrel-requests/issues/new/choose)
- [ ] I have added tests that prove my fix is effective or that my
feature works.
- [ ] I have added (or requested a maintainer to add) the necessary
`Breaking*` or `New Feature` labels where relevant.
- [ ] I have done my best to ensure that my PR adheres to [the Fuel Labs
Code Review
Standards](https://github.com/FuelLabs/rfcs/blob/master/text/code-standards/external-contributors.md).
- [ ] I have requested a review from the relevant team or maintainers.

---------

Co-authored-by: z <zees-dev@users.noreply.github.com>
2025-07-24 08:18:31 -07:00
..
examples Implement partial equivalence and extend forc migrate tool (#6900) 2025-02-11 10:02:45 -03:00
src feat: forc mcp server - with forc-call tool integration (#7284) 2025-07-24 08:18:31 -07:00
Cargo.toml Bump fuel deps (#7228) 2025-06-23 13:05:53 +04:00
README.md remove archived forc-explore plugin from CI and docs (#7257) 2025-06-27 12:53:25 +00:00

mdbook-forc-preprocessor

A preprocessor for mdBook to update the Forc commands and plugins section of the Sway book based on the output we get when running forc --help.

This preprocessor is automatically run on every build, as long as the book.toml file contains the preprocessor:

[preprocessor.forc-documenter]

The preprocessor runs with strict mode off by default to enable building the book regardless of errors in the Forc Reference pages. To check if pages should be added or removed, run with the strict environment variable:

MDBOOK_preprocessor__FORC_documenter__STRICT="true" mdbook build docs/book

Usage

Adding a new forc command

Enter a new entry under the Commands section within SUMMARY.md, in this format:

- [forc fmt](./forc_fmt.md)

Adding a new forc plugin

Do the same as the above, with an extra step of adding an installation step within the CI. The preprocessor needs to be aware of the plugin when building the book, since it is calling forc <plugin> --help to generate the documentation. You can add this installation step within ci.yml and gh-pages.yml.

Removing a forc command

Delete the entry from SUMMARY.md.

Removing a forc plugin

Do the same as the above, with an extra step of removing the installation command within ci.yml and gh-pages.yml.

Adding an example

Create a new Markdown file within scripts/mdbook-forc-documenter/examples, named after the desired forc command or plugin in snake case. The preprocessor automatically detects the example if there is a matching forc command or plugin with the same name as the file name, and includes it in the build.

Removing an example

Delete the Markdown file from within the above examples directory.