Skip to content

[Bug] Bundled MCP server auth/channel tools fail or stall while REST API works with same agent key #70

@tstack77

Description

@tstack77
# Bundled MCP server auth/channel tools fail or stall while REST API works with same agent key

## Summary

The bundled Canopy MCP server appears to fail or stall when invoking basic tools such as `canopy_list_channels`, even though the same API key works correctly against the documented `/api/v1` REST endpoints.

This seems to happen because the MCP server initializes its own Canopy app context with `create_app()` and internal managers instead of calling the already-running Canopy REST API.

## Environment

- Canopy version observed: `0.6.32`
- Canopy source path: `/home/stack/apps/canopy-src`
- Canopy data root: `/home/stack/data/canopy`
- Service: `canopy.service`
- Service working directory: `/home/stack/apps/canopy-src`
- Service environment:
  - `CANOPY_DATA_ROOT=/home/stack/data/canopy`
  - `PYTHONUNBUFFERED=1`
- Service exec:
  - `/home/stack/apps/canopy-src/venv/bin/python -m canopy --host 0.0.0.0`
- Web/API endpoint:
  - `http://localhost:7770`
  - reverse proxied separately through Nginx Proxy Manager

## Account/key setup

A Canopy account exists:

- username: `coo`
- display name: `COO`
- account type: `agent`
- status: active

A newly generated API key for this agent works through REST.

## REST API works

Using the same key intended for MCP:

```bash
curl -s http://localhost:7770/api/v1/agents/me \
  -H "X-API-Key: $CANOPY_API_KEY"

returns:

{
  "account_type": "agent",
  "display_name": "COO",
  "username": "coo"
}

And:

curl -s http://localhost:7770/api/v1/channels \
  -H "X-API-Key: $CANOPY_API_KEY"

successfully returns visible channels, including coo, general, and agent-start-here.

Other REST endpoints also return successfully:

/api/v1/agents/me
/api/v1/channels
/api/v1/messages
/api/v1/agents/me/inbox
/api/v1/agents/me/heartbeat
/api/v1/agents/me/catchup

MCP setup

MCP server is launched from the Canopy repo root using a wrapper:

#!/usr/bin/env bash
set -euo pipefail

CANOPY_SRC="/home/stack/apps/canopy-src"
CANOPY_ENV="/home/stack/.config/hermes-secrets/canopy-coo.env"

cd "$CANOPY_SRC"
mkdir -p logs

export PYTHONPATH="$CANOPY_SRC"
export CANOPY_BASE_URL="http://localhost:7770"
export CANOPY_DATA_ROOT="/home/stack/data/canopy"
export PYTHONUNBUFFERED=1

if [[ -z "${CANOPY_API_KEY:-}" && -f "$CANOPY_ENV" ]]; then
  source "$CANOPY_ENV"
fi

if [[ -z "${CANOPY_API_KEY:-}" ]]; then
  echo "ERROR: CANOPY_API_KEY is not set" >&2
  exit 1
fi

"$CANOPY_SRC/.venv/bin/python" "$CANOPY_SRC/start_mcp_server.py"

Manual startup test succeeds:

timeout 5s /home/stack/bin/canopy-mcp-coo.sh

Output:

INFO:__main__:Starting Canopy MCP Server (July 2025 Edition)
INFO:__main__:Project root: /home/stack/apps/canopy-src
INFO:__main__:API Key configured
INFO:__main__:Running MCP server with stdio transport for Cursor.ai
exit=124

exit=124 is expected because timeout kills the long-running stdio MCP server.

MCP behavior

With tool filtering enabled, the MCP tool catalog loads successfully and exposes only:

mcp_canopy_canopy_list_channels
mcp_canopy_get_prompt
mcp_canopy_list_prompts
mcp_canopy_list_resources
mcp_canopy_read_resource

However, invoking:

mcp_canopy_canopy_list_channels

either returns:

Authentication failed. Please check your API key.

or stalls until manually interrupted.

This happens even though the same key successfully authenticates and lists channels through REST.

Relevant code observation

In canopy/mcp/server.py, the MCP server appears to authenticate by creating a new local app instance:

app = create_app()
with app.app_context():
    (_, api_key_manager, _, _, _, _, _, _, _, _, _) = _get_app_components_any(app)
    self.key_info = api_key_manager.validate_key(self.api_key)

And canopy_list_channels also creates a new app context and uses internal managers:

app = create_app()
with app.app_context():
    ...
    channels = channel_manager.get_user_channels(self.user_id)

This means the MCP server is not simply calling the already-running Canopy API at:

http://localhost:7770/api/v1/channels

Expected behavior

If the API key works with:

GET /api/v1/agents/me
GET /api/v1/channels

then the MCP tools using the same key should also work, or the MCP docs should specify what additional runtime/data-root/meshspace configuration is required.

At minimum, canopy_list_channels should return the same channels as:

curl -H "X-API-Key: $CANOPY_API_KEY" \
  http://localhost:7770/api/v1/channels

Actual behavior

REST works with the agent key.

Bundled MCP tool invocation fails authentication or stalls.

Additional issue: strict tool schema problem

When the full Canopy MCP tool catalog is exposed to an OpenAI-compatible tool-calling client, one tool fails schema validation:

Invalid schema for function 'mcp_canopy_canopy_create_request':
In context=('properties', 'tags'), array schema missing items.

The tags array schema likely needs:

"items": { "type": "string" }

This requires tool filtering to avoid registering the broken tool.

Possible root cause

The bundled MCP server may be too tightly coupled to direct internal Canopy app initialization. In a running service deployment, this may create a second local app/runtime context that does not behave the same as the already-running Canopy service.

Observed variants:

  1. Without matching data-root environment, MCP reports authentication failure.
  2. With CANOPY_DATA_ROOT=/home/stack/data/canopy, MCP tool invocation can stall.
  3. REST against the running service works consistently.

Suggested fix

Prefer making the bundled MCP server act as a client of the running Canopy REST API instead of initializing a second local Canopy app context.

For example, canopy_list_channels could call:

GET http://localhost:7770/api/v1/channels
X-API-Key: <CANOPY_API_KEY>

and return the same result as the REST API.

Alternatively, document the exact required environment variables for MCP to bind to the same meshspace/runtime/data root as the running service, including any locking/concurrency implications.

Reproduction steps

  1. Run Canopy as a system service with:
WorkingDirectory=/home/stack/apps/canopy-src
CANOPY_DATA_ROOT=/home/stack/data/canopy
python -m canopy --host 0.0.0.0
  1. Create an agent account and API key.

  2. Verify REST succeeds:

curl -s http://localhost:7770/api/v1/agents/me \
  -H "X-API-Key: $CANOPY_API_KEY"

curl -s http://localhost:7770/api/v1/channels \
  -H "X-API-Key: $CANOPY_API_KEY"
  1. Start bundled MCP server from repo root:
CANOPY_API_KEY="$CANOPY_API_KEY" \
CANOPY_DATA_ROOT="/home/stack/data/canopy" \
PYTHONPATH="/home/stack/apps/canopy-src" \
/home/stack/apps/canopy-src/.venv/bin/python \
/home/stack/apps/canopy-src/start_mcp_server.py
  1. Invoke canopy_list_channels through an MCP client.

  2. Observe authentication failure or stall.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions