Skip to content

feat: add MCP server for AI agent interactions - #49

Open
vycdev2 wants to merge 3 commits into
vycdev:developfrom
vycdev2:feature/mcp-server
Open

feat: add MCP server for AI agent interactions#49
vycdev2 wants to merge 3 commits into
vycdev:developfrom
vycdev2:feature/mcp-server

Conversation

@vycdev2

@vycdev2 vycdev2 commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Replace the custom REST-style endpoints with the official ModelContextProtocol.AspNetCore Streamable HTTP transport at /api/mcp.
  • Disable MCP unless MCP_API_KEY is configured, require bearer authentication, validate exact configured origins, and apply per-client fixed-window rate limiting before authentication.
  • Limit the read-only tool surface to aggregate activity/guild data, guild-scoped leaderboards, and approved non-removed quotes; logs, balances, user exports, pending quotes, and removed quotes are not exposed.
  • Share the documented DASHBOARD_API_URLS listener rather than loading an unused MCP listener setting.
  • Add endpoint-level tests for credentials, origins/CORS, rate limiting, current and legacy MCP protocol flows, tool discovery/calls, and pending-quote exclusion.

Verification

  • dotnet build --consoleLoggerParameters:ErrorsOnly — passed: 0 errors (2 warnings reported).
  • dotnet test Morpheus.Tests/Morpheus.Tests.csproj --no-build --filter "FullyQualifiedName~Mcp" — passed: 14/14.
  • dotnet test --no-build — 314 passed, 2 failed: pre-existing MiscModuleTests.NormalizeTimeUntilEventName_NormalizesCase cases require tr-TR, which is unavailable because this runner has DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=1.
  • git diff --check — passed.

Risk

  • Medium — this adds a network-facing protocol endpoint and SDK dependency, but the endpoint is disabled by default, authenticated when enabled, origin-restricted, rate-limited, read-only, and covered by transport-level tests.

Closes #3

This was generated by an AI agent (vycdev2). Please verify any changes before merging or applying.

Implements an HTTP-based MCP (Model Context Protocol) server that exposes
Morpheus bot data and functionality to AI agents through a clean tool-based API.

Endpoints:
- GET /api/mcp - Server info and available tools
- GET /api/mcp/health - Health check
- GET /api/mcp/tools - List all available tools with parameter schemas
- POST /api/mcp/call/{toolName} - Execute a tool with parameters

Tools:
- get_user_stats - User statistics (balance, XP, level, messages, quotes)
- get_guild_info - Guild/server information with settings
- get_economy_summary - Economy overview (balances, UBI pool, vault, stocks)
- get_activity_overview - Global activity metrics
- get_guilds - List all servers with activity stats
- get_users - Paginated user list
- get_quotes - Paginated quotes with filtering
- get_quote_by_id - Single quote details
- get_recent_logs - Recent bot logs with severity filtering
- get_stock_summary - Stock market gainers/losers
- get_leaderboard - Activity leaderboard by XP or messages

Closes vycdev#3

@vycdev vycdev left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for putting this together. The database-query layer builds and its tests pass, but this HTTP surface is not safe or MCP-compatible yet. Before merging, it needs enforced authentication and authorization, rate limiting, restricted/validated origins, standard MCP protocol support (or explicit REST API naming), endpoint-level security/protocol tests, and careful review of which data may be exposed. In particular, unapproved quotes and recent logs should not be broadly accessible. The current MCP_API_KEY and MCP_API_URLS settings give a false sense of protection/configurability because neither is actually applied.

Comment thread MCP/McpApiExtensions.cs Outdated

RouteGroupBuilder api = app
.MapGroup("/api/mcp")
.RequireCors(CorsPolicyName);

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Blocking: this group only applies CORS; McpApiOptions.ApiKey is never validated. The health endpoint can report authEnabled: true while every tool remains callable without a key, including tools returning users, balances, unapproved quotes, and logs. Add authentication/authorization middleware or an endpoint filter, plus integration tests for missing, incorrect, and correct credentials.

Comment thread MCP/McpApiExtensions.cs Outdated
corsOptions.AddPolicy(CorsPolicyName, policy =>
{
policy
.AllowAnyOrigin()

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Blocking for a network-facing data API: AllowAnyOrigin() permits any browser origin, while MCP's HTTP transport requires validating the Origin header to prevent DNS-rebinding attacks. Use an explicit configured allowlist and test rejected origins.

Comment thread MCP/McpApiExtensions.cs Outdated
}));

// Call a specific tool
api.MapPost("/call/{toolName}", async (

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a custom REST call endpoint, not the MCP protocol expected by standard clients. MCP uses JSON-RPC with initialization and tools/list / tools/call over its transport endpoint. Please implement the standard protocol (preferably with an MCP SDK), or present this explicitly as an agent-friendly REST API rather than an MCP server.

Comment thread Program.cs
Env.Load(".env");

DashboardApiOptions dashboardOptions = DashboardApiOptions.FromEnvironment();
McpApiOptions mcpOptions = McpApiOptions.FromEnvironment();

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MCP_API_URLS has no effect: mcpOptions.Urls is loaded here, but the host is bound only with dashboardOptions.Urls. This silently exposes the new routes on the dashboard listener instead of the configured MCP URL. Either intentionally share and document one listener or wire the configuration correctly.

@vycdev2

vycdev2 commented Aug 4, 2026

Copy link
Copy Markdown
Contributor Author

Addressed the requested changes in 2235556:

  • replaced the custom REST surface with the official MCP SDK and standard Streamable HTTP protocol;
  • enforced bearer-key authentication, exact Origin validation, and rate limiting (including failed-authentication attempts);
  • removed the unused MCP_API_URLS setting and documented the intentionally shared listener;
  • narrowed the tools so logs, balances, user-directory exports, pending quotes, and removed quotes are not exposed;
  • added endpoint tests for missing/incorrect/correct credentials, rejected/allowed origins, browser preflight, rate limiting, MCP protocol revisions, discovery, calls, and pending-quote exclusion.

The MCP-focused tests pass 14/14. The full suite reports 314 passing and the same two invariant-globalization failures in MiscModuleTests because this runner cannot load tr-TR.

This was generated by an AI agent (vycdev2). Please verify any changes before merging or applying.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants