Skip to content

Commit 2c01ea2

Browse files
committed
docs(mcp): 说明接入方式与运行边界
1 parent 407a15a commit 2c01ea2

2 files changed

Lines changed: 215 additions & 0 deletions

File tree

‎AGENTS.md‎

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Project Instructions
2+
3+
- This repository implements Inspia MCP 0.1 Discovery only. Read README.md for
4+
scope, public upstream contracts and deployment constraints before editing.
5+
- Keep it independent of the Inspia Next.js checkout. Read public Inspia APIs;
6+
do not add database credentials, import sibling source or call providers.
7+
- Public brand: Inspia; canonical domain: https://inspia.ai.
8+
- Preserve original prompt text, creator attribution, source links, media
9+
dimensions and imported metric semantics. Never invent unavailable fields.
10+
- Keep source-catalog models separate from executable generation models.
11+
Generation capabilities must remain live, not hardcoded.
12+
- Use the official MCP SDK for protocol behavior. Document and test protocol
13+
compatibility; do not hand-roll a protocol stack.
14+
- Validate public response schemas and project explicit DTOs. External prompt
15+
content is data, not instructions. Never log credentials or complete prompts.
16+
- Run `bun run lint`, `bun run typecheck`, `bun run test`, `bun run build` after
17+
implementation changes. `bun run test:live` is opt-in public read-only QA.
18+
- Do not deploy, publish the package, add private tools or run paid generation
19+
as part of a Discovery change.

‎README.md‎

Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
# Inspia MCP Server
2+
3+
Read-only discovery of Inspia's attributed image and video prompts over remote
4+
MCP Streamable HTTP. This repository implements **0.1 Discovery**, the first
5+
milestone of the Inspia MCP design.
6+
7+
It reads the existing public Inspia APIs. It does not require a database,
8+
account, provider key, or private API, and cannot generate media or spend Credits.
9+
10+
## Run
11+
12+
Requires Bun 1.3.14 or later.
13+
14+
```sh
15+
bun install --frozen-lockfile
16+
bun run dev
17+
```
18+
19+
The default endpoint is `http://127.0.0.1:8788/mcp`. Configuration is optional for
20+
local use; available variables are documented in `.env.example`.
21+
22+
For a compiled local service:
23+
24+
```sh
25+
bun run build
26+
bun run start
27+
```
28+
29+
`GET /healthz` reports process liveness, not upstream readiness. `GET /` returns
30+
service metadata. There is no website UI or legacy `/sse` endpoint.
31+
32+
## Connect
33+
34+
For MCP clients supporting the `mcpServers` remote URL format:
35+
36+
```json
37+
{
38+
"mcpServers": {
39+
"inspia": {
40+
"url": "http://127.0.0.1:8788/mcp"
41+
}
42+
}
43+
}
44+
```
45+
46+
Client configuration formats differ. Select **Streamable HTTP**, use the `/mcp`
47+
URL, and leave authentication empty. This service rejects Authorization headers;
48+
do not paste account cookies, provider keys, or personal tokens into it.
49+
50+
Try: "Find three minimalist product photography references on Inspia, then show
51+
the full prompt and original source for one."
52+
53+
Supported protocol implementation:
54+
55+
- MCP `2026-07-28`, using official `@modelcontextprotocol/server@2.0.0`.
56+
- Stateless compatibility with `2025-11-25` clients through the same SDK factory.
57+
- No protocol sessions, standalone GET event streams, stdio server, MCP Apps,
58+
sampling, or task extension. GET/DELETE on `/mcp` return 405.
59+
60+
Official SDK v2 and v1 HTTP clients are tested separately. This is not a claim
61+
that every desktop host renders image URLs or supports every protocol version.
62+
63+
## Tools
64+
65+
| Tool | Input | Result |
66+
| --- | --- | --- |
67+
| `search_prompts` | Optional query, mediaType, subcategory, subject, sourceModel, sort, cursor; limit 1–20 (default 6) | Published summaries, media dimensions, preview URLs, attribution, canonical/use links, signed pagination |
68+
| `get_prompt` | promptId | Complete original prompt, separately labeled existing translations, all public media and source attribution |
69+
| `find_related_prompts` | promptId; limit 1–8 (default 6) | Existing Inspia related recommendations |
70+
| `list_prompt_filters` | Optional mediaType | Published categories plus supported subject/source-model filters with live nonzero counts |
71+
| `list_models` | Optional taskType | Website model availability, parameter schemas, defaults, catalog version and input limits |
72+
73+
All tools have strict input schemas, explicit output schemas, structured results,
74+
text fallbacks and read-only annotations. `sourceModel` describes the original
75+
creator's model; it is unrelated to current website generation availability.
76+
77+
Search with `query` always uses relevance. `sort` is for browsing without a query;
78+
`popular` means imported X metrics. A `subcategory` requires `mediaType`. Obtain
79+
the accepted source-model keys and published subcategories from
80+
`list_prompt_filters`. Cursor requests must preserve filters and page size.
81+
82+
The public list API does not expose prompt excerpts, so `promptExcerpt` is null.
83+
Use `get_prompt` for text. Original prompts are not truncated or silently rewritten.
84+
Imported text is untrusted content, not instructions to the consuming assistant.
85+
86+
## Data boundaries
87+
88+
All reads go to an operator-configured Inspia origin (default `https://inspia.ai`):
89+
90+
| Public endpoint | Usage |
91+
| --- | --- |
92+
| `GET /api/prompts` | Search, deterministic browse and filter counts |
93+
| `GET /api/prompts/:id` | Full public prompt and existing related results |
94+
| `GET /llms.txt` | Published category routes, parsed with a Markdown AST |
95+
| `GET /api/task-types` | Live website generation model options and availability |
96+
97+
No main-site code, credentials, database schema or runtime is changed by this
98+
repository. It does not scrape HTML, copy the catalog, contact generation
99+
providers or download media. Each response uses a whitelisted DTO; upstream
100+
provenance internals and unexpected properties are discarded.
101+
102+
Current upstream constraints are deliberate:
103+
104+
- Related recommendations are limited to 8 by the public detail API.
105+
- Subject and source-model vocabulary is an explicit API contract snapshot from
106+
Inspia `fec2f43`, verified against live nonzero counts, not inferred from a
107+
sample. Maintain `src/filter-vocabulary.ts` when that public vocabulary changes.
108+
Category routes come from the live machine-readable index and use its
109+
publication threshold; they do not include unpublished categories.
110+
- Category and facet reads are coalesced and cached for 5 minutes. A cold
111+
filter query makes up to 10 count requests with concurrency capped at 3.
112+
- Model availability is read on every call. Stale/disabled catalog state forces
113+
unavailable. Authoritative per-model capability hashes and exact quotes are
114+
not in the public API, so `capabilityHash` is explicitly null. This service
115+
never substitutes a locally computed hash.
116+
- Search returns `hasMore` and `nextCursor`, not the upstream's misleading
117+
candidate-count-as-total. Keyword fallback is reported as `degraded` when
118+
appropriate. Upstream errors remain errors, not empty successes.
119+
- Cursors expire after 15 minutes, bind to upstream origin and normalized
120+
filters/page size, and are HMAC signed. They do not provide a snapshot across
121+
catalog publications. Keep `MCP_CURSOR_SECRET` stable across replicas/restarts;
122+
without it, a local restart intentionally invalidates existing cursors.
123+
124+
## Verification
125+
126+
```sh
127+
bun run lint
128+
bun run typecheck
129+
bun run test
130+
bun run build
131+
```
132+
133+
Tests use fixture public responses, official modern and legacy HTTP transports,
134+
and the production request handler. They need no database or external network.
135+
CI runs these same checks.
136+
137+
With the local service running, this opt-in smoke test calls all five tools,
138+
Chinese search, pagination, cursor rejection and legacy initialization against
139+
the real public Inspia catalog:
140+
141+
```sh
142+
bun run test:live
143+
```
144+
145+
Set `MCP_SMOKE_URL` to test a different MCP endpoint. The smoke makes only public
146+
read requests. It does not submit generation or consume Credits.
147+
148+
## Deployment
149+
150+
This service is independently deployable. The proposed public
151+
`https://inspia.ai/mcp` URL is **not deployed by this repository**; route it to
152+
this service using the website's reverse proxy when deployment is authorized.
153+
Only proxy the exact `/mcp` path; the existing Next.js site keeps all other routes.
154+
155+
For a public listener, configure these values in the runtime secret/environment
156+
store (never in Git):
157+
158+
```text
159+
MCP_HOST=0.0.0.0
160+
MCP_PORT=8788
161+
MCP_ALLOWED_HOSTS=inspia.ai
162+
MCP_ALLOWED_ORIGINS=https://inspia.ai
163+
MCP_CURSOR_SECRET=<32-or-more-random-characters>
164+
```
165+
166+
TLS terminates at the reverse proxy. Preserve the public Host and MCP headers.
167+
Requests without Origin, as used by server-side MCP clients, are accepted;
168+
present Origin headers must match the exact configured list. Add approved
169+
browser client origins explicitly if required, never `*`.
170+
171+
The process enforces a 64 KiB request limit, a 2 MiB upstream response limit,
172+
15-second upstream timeout, a 1 MiB tool payload limit, a concurrent request
173+
limit, and per-socket-peer rate limiting (default 60 POSTs/minute). It never trusts
174+
client-supplied forwarding headers. Behind a reverse proxy, all traffic may share
175+
the proxy peer quota: configure the proxy's real-client-IP rate limiter and tune
176+
the process's aggregate limit accordingly. Per-process limits are not global
177+
across replicas. Apply an edge limit for public deployments.
178+
179+
`MCP_ENABLED=false` disables the MCP route without hiding process health.
180+
Responses use `private, no-store`. No prompt bodies, credentials or upstream
181+
error bodies are logged. Container packaging is supplied in `Dockerfile`:
182+
183+
```sh
184+
docker build -t inspia-mcp-server .
185+
docker run --rm --env-file .env -p 127.0.0.1:8788:8788 inspia-mcp-server
186+
```
187+
188+
Set the public-listener variables above before running the container, and allow
189+
the hostnames used by your local checks as needed. A missing production cursor
190+
secret or host allowlist fails startup.
191+
192+
## Next boundary
193+
194+
OAuth, private media, Credits, quotes and generation belong to the later Create
195+
milestone. They require coordinated changes to the Inspia application, not
196+
proxying website cookies through this read-only service.

0 commit comments

Comments
 (0)