Update docs and solution file for the stdio MCP server's removal
The prior commit's git add silently dropped these five files because one path in the same invocation didn't exist. Docs, solution file, and example config still needed the paired update: Novelly.slnx drops the Novelly.Mcp project entry, README and CLAUDE.md describe MCP as an in-API HTTP endpoint instead of a stdio binary, .mcp.json.example uses the type: http shape, and outline-importer.md's tool references are fixed to real tool names.
This commit is contained in:
@@ -6,22 +6,21 @@
|
||||
|
||||
Software for planning and writing a novel. You outline the book, keep character
|
||||
dossiers, break chapters into scenes, and draft prose — with a Claude-powered agent
|
||||
embedded in the app that can read and edit the same data you can, and an MCP server that
|
||||
exposes that data to Claude Code, Claude Desktop, or any other MCP client.
|
||||
embedded in the app that can read and edit the same data you can, and an MCP endpoint that
|
||||
exposes that same data to Claude Code, Claude Desktop, or any other MCP client.
|
||||
|
||||
The point of the three-way arrangement is that there is exactly one source of truth. The
|
||||
React UI, the embedded agent, and the MCP server all go through the same REST API, so an
|
||||
edit made from a chat in Claude Code and an edit made by typing in the browser are the
|
||||
same edit.
|
||||
React UI's REST calls, the embedded agent, and MCP clients all resolve to the same
|
||||
application services in-process, so an edit made from a chat in Claude Code and an edit
|
||||
made by typing in the browser are the same edit.
|
||||
|
||||
## Stack
|
||||
|
||||
| Piece | Built with |
|
||||
|---|---|
|
||||
| `Novelly.Api` | ASP.NET Core 10 minimal APIs, EF Core 10 + SQLite, Anthropic SDK, OpenAPI |
|
||||
| `Novelly.Api` | ASP.NET Core 10 minimal APIs, EF Core 10 + SQLite, Anthropic SDK, OpenAPI, MCP over Streamable HTTP (`ModelContextProtocol.AspNetCore`) |
|
||||
| `Novelly.AppHost` | .NET Aspire orchestration for the API and the web client |
|
||||
| `Novelly.ServiceDefaults` | Shared OpenTelemetry, health checks and service discovery |
|
||||
| `Novelly.Mcp` | MCP stdio server (`ModelContextProtocol`) |
|
||||
| `Novelly.Web` | React 19, TypeScript, Vite, TanStack Query, Tailwind v4 |
|
||||
|
||||
The back end is one project organised by feature, not by layer. Each feature folder —
|
||||
@@ -192,19 +191,10 @@ A few deliberate choices worth knowing about:
|
||||
|
||||
## The MCP server
|
||||
|
||||
A stdio MCP server exposing 45 tools over the same REST API. It holds no domain logic of
|
||||
its own — it is a second front end, not a second implementation.
|
||||
|
||||
Build it, then point your MCP client at the produced binary:
|
||||
|
||||
```bash
|
||||
./scripts/publish-mcp.sh
|
||||
```
|
||||
|
||||
Aspire does not run or manage this process — it's a separate stdio subprocess your MCP
|
||||
client spawns directly, so nothing rebuilds it automatically. Re-run the script (and
|
||||
reconnect your MCP client) after pulling changes that touch `src/Novelly.Mcp`, or it keeps
|
||||
serving whatever was published last, including against a stale auth contract.
|
||||
The API itself serves MCP over Streamable HTTP at `POST /mcp`, exposing 45 tools that call
|
||||
the same application services the REST endpoints and the embedded web agent call — it holds
|
||||
no domain logic of its own, and there's nothing to build or publish separately. The API
|
||||
process just needs to be running; there's no separate subprocess to keep in sync with it.
|
||||
|
||||
Copy `.mcp.json.example` to `.mcp.json` (gitignored, since it carries your API key) and
|
||||
fill in the key:
|
||||
@@ -213,10 +203,10 @@ fill in the key:
|
||||
{
|
||||
"mcpServers": {
|
||||
"novelly": {
|
||||
"command": "/absolute/path/to/mcp-server/Novelly.Mcp",
|
||||
"env": {
|
||||
"NOVELLY_API_URL": "http://localhost:5080",
|
||||
"NOVELLY_API_KEY": "<matches the API's Auth:ServiceApiKey user secret>"
|
||||
"type": "http",
|
||||
"url": "http://localhost:5080/mcp",
|
||||
"headers": {
|
||||
"X-Novelly-Api-Key": "<matches the API's Auth:ServiceApiKey user secret>"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -225,8 +215,12 @@ fill in the key:
|
||||
|
||||
The API must be running, with `Auth:ServiceApiKey` set (e.g. via
|
||||
`dotnet user-secrets set Auth:ServiceApiKey <key> -p src/Novelly.Api`) to the same value
|
||||
as `NOVELLY_API_KEY` above. If the API is not running, or the key is missing or mismatched,
|
||||
the tools say so in a message the model can act on rather than failing opaquely.
|
||||
as the `X-Novelly-Api-Key` header above. If the API is not running, or the key is missing or
|
||||
mismatched, the request 401s.
|
||||
|
||||
Tool argument names are camelCase, matching the REST API and every other MCP argument name
|
||||
this project has ever used. `create_novel` called over MCP is owned by the seeded service
|
||||
user (an Admin), not whichever person is signed into the web app.
|
||||
|
||||
### Importing an existing outline
|
||||
|
||||
|
||||
Reference in New Issue
Block a user