Skip to main content

Local development

Running the MCP (Model Context Protocol) Services from source against a local OctoMesh stack on your own machine.

Prerequisites

  • .NET 10 SDK
  • The OctoMesh backend services running locally — see Developer Guide → Getting started and Developer PowerShell for the Start-Octo workflow
  • MongoDB reachable (the default Start-Octo infrastructure exposes it on localhost:27017)
  • octo-cli available — used during one-time tenant bootstrap and as the reference behaviour for new tools

Start the backend services first

The MCP Services calls Identity / Asset / Communication / Bot / Reporting / AdminPanel over HTTP. The Start-Octo PowerShell cmdlet starts them natively on the dev machine:

Start-Octo -nonInteractive $true

The ports each service binds locally (used by appsettings.json defaults — see Configuration):

ServiceHTTPS
Assethttps://localhost:5001/
Identityhttps://localhost:5003/
Communicationhttps://localhost:5005/
Bothttps://localhost:5007/
Reportinghttps://localhost:5009/
AdminPanelhttps://localhost:5011/

Stop them with Stop-Octo when you're done.

Run the MCP Services from source

cd octo-mcp-service/src/McpServices
dotnet run --environment Development

In Development mode the server reads appsettings.json + appsettings.Development.json and exposes both transports:

TransportURL
HTTPhttp://localhost:5016/mcp
HTTPShttps://localhost:5017/mcp

The HTTPS port uses the local dev certificate (dotnet dev-certs https --trust if your OS doesn't trust it yet).

The dev server enumerates roughly 187 tool methods at startup. Tail the output to confirm a clean boot — startup errors surface as logged exceptions before the host begins listening.

Register your local server with Claude Code

# HTTP (most common — no cert hassle)
claude mcp add --transport http --scope local octomesh-local http://localhost:5016/mcp

# HTTPS (only if your dev profile binds HTTPS and you trust the dev cert)
claude mcp add --transport http --scope local octomesh-local https://localhost:5017/mcp
// Claude Desktop — claude_desktop_config.json
{
"mcpServers": {
"octomesh-local": {
"type": "http",
"url": "http://localhost:5016/mcp"
}
}
}

Verify:

claude mcp list
# octomesh-local: http://localhost:5016/mcp (HTTP) - ✓ Connected

Restart Claude Code so the tool catalogue is enumerated. First tool call against the local server should be authenticate(tenantId="<your local tenant>") to start the OAuth Device Flow against the locally-running Identity service.

Legacy stdio bridge

Earlier versions shipped src/mcp-bridge.js, a Node-based stdio→HTTPS shim required by older Claude Code releases. That shim has been removed. Direct HTTP registration is simpler, supports per-call tenant routing, and avoids NODE_TLS_REJECT_UNAUTHORIZED=0.

Running the test suite

# Full suite (~400 tests, ~250 ms)
dotnet test Octo.McpServices.sln -c DebugL

# Filter to a single tool class
dotnet test --filter "FullyQualifiedName~TenantManagementToolsTests"

# CI parity (uses Release + private NuGet feed)
dotnet test Octo.McpServices.sln -c Release

The CI build runs in Release against the private NuGet feed ($(nugetPrivateServer)), not DebugL. Mirror this locally when you suspect a config-sensitive failure.

Pitfalls during local-dev

  • CkTypeId format is Name-VersionUint, not SemVer. new CkTypeId("MyType-1") works; new CkTypeId("MyType-1.0.0") throws because the SDK parses the version as uint.
  • OctoObjectId must be a 24-character hex string. Use realistic values like "507f1f77bcf86cd799439011" in tests.
  • Don't reuse SDK clients across requests. The SDK clients cache ServiceUri on first use; sharing one across tenants routes the second call to the wrong tenant. Always go through IOctoServiceClientFactory.Create*Client(tenantId, accessToken) — the *ClientContext.TryBuild helpers do this for you.
  • TreatWarningsAsErrors is on. Missing XML doc on a public member (CS1591) fails the build.

For the full conventions catalogue (response envelope, optimistic locking, file-transfer architecture, aggregation mapper) see CLAUDE.md in the repository.