跳到主要內容

ARC developer documentation

Connect a client

Point an MCP client at a blocklet host over streamable HTTP, then confirm the connection with an anonymous tools/list that needs no handshake.

Connect an MCP client to a blocklet by giving it the host URL plus /mcp.

<host> is the domain the blocklet is served at, the same one you would open in a browser. If you are unsure you have the right one, GET https://<host>/.well-known/mcp.json and check its url field: it echoes the endpoint the runtime believes it is serving.

bash
claude mcp add --transport http arc https://<host>/mcp

No header and no client id are needed to connect. The endpoint accepts anonymous requests and answers the read tools; a credential is only required once you call a write tool.

For the exact commands for Claude Code and Codex CLI, see Connect your tool.

Confirm it without a client

The endpoint is plain HTTP, so curl is enough to check a host before you wire up an agent.

bash
curl -s -X POST https://<host>/mcp \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'

A blocklet that declares no content collections answers with eight tools:

text
afs_read  afs_list  afs_write  afs_delete  afs_search  afs_exec  afs_stat  afs_explain

A blocklet that declares content collections answers with those eight plus three more:

text
search_content  list_content  get_content

Which set you get depends on the blocklet's own declaration, not on your credential. See Tools.

initialize is not required

The request above sends tools/list directly, with no preceding initialize, and returns 200.

The endpoint is stateless. It does not issue an mcp-session-id, so there is no session for a client to hold, lose, or resynchronise. A client can send a stale session id and the request still succeeds; a runtime restart does not invalidate anything on the client side.

This matters for long-lived agents: there is no reconnect handshake to implement.

What anonymous access gives you

The handshake, the three list methods, and the read tools. Write, delete, and exec return 401 with a challenge, and so does any method not on the list. The rule is fail-closed.

Whether an allowed read actually returns data is a separate question, decided by what the blocklet declared. Both rules are set out in Access tiers.

When you need to write

Calling a write tool without a credential returns the challenge that starts authorization:

bash
curl -s -i -X POST https://<host>/mcp \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -d '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"afs_write","arguments":{"path":"/tmp/x","content":"x"}}}'
text
HTTP/1.1 401 Unauthorized
www-authenticate: Bearer resource_metadata="https://<host>/.well-known/oauth-protected-resource"

{"error":"Unauthorized"}

Follow that URL to continue. See Authorize a client.

Connecting a stdio-only client

Clients that speak MCP over stdio and cannot open an HTTP transport need a bridge. Use arc mcp, which bridges stdio to a running local daemon.

The bridge is a compatibility path for those clients. If your client supports streamable HTTP, connect to /mcp directly and skip it.

Local runtime

Against a local Node runtime, a request from the same machine is a verified socket peer and is granted operator access, so write tools answer without a credential. That is the loopback tier; it does not exist over the network and it is not how a deployed blocklet behaves. Use a remote host to exercise the anonymous and authenticated paths.