fyi-docs
by bruce212
README.md
# fyi-docs-mcp-ts
Remote **MCP server** for **FYI Docs** (document management system), built with **Bun** + TypeScript and deployed on **Railway**.
Exposes read-only FYI tools to MCP clients (Claude, Cursor, etc.) over **Streamable HTTP** for Somerset Accountancy Services.
## Stack
| Component | Choice |
|-----------|--------|
| Runtime | Bun |
| Language | TypeScript (strict) |
| MCP SDK | `@modelcontextprotocol/sdk` |
| Transport | Streamable HTTP (Web Standard, Bun-native) |
| Validation | Zod |
| Hosting | Railway (GitHub-connected) |
## Tools
| Tool | Description |
|------|-------------|
| `search_documents` | Search/list documents |
| `search_clients` | Search/list clients (`/entity`) |
| `list_jobs` | List jobs |
| `list_tasks` | List tasks |
| `list_cabinets` | List filing cabinets |
| `fyi_raw_list` | Low-level list against any FYI resource |
| `check_fyi_connection` | Verify credentials / connectivity |
All tools are **read-only** in v1. Responses are summarised; secrets are redacted.
## Endpoints
| Path | Purpose |
|------|---------|
| `GET /health` | Railway health check (200) |
| `ALL /mcp` | MCP Streamable HTTP endpoint |
| `GET /` | Service metadata |
## Environment variables
**Required**
```
FYI_ACCESS_ID=
FYI_ACCESS_SECRET=
FYI_REGION=uk
MCP_API_KEY= # shared secret for /mcp (min 16 chars)
```
**Optional**
```
FYI_APPLICATION_ID=
FYI_API_USER=
FYI_BASE_URL=
PORT=3000
NODE_ENV=production
```
| `FYI_REGION` | Base URL |
|--------------|----------|
| `uk` | `https://api-eu-west-2.fyi.app/external` |
| `au` / `anz` | `https://api-ap-southeast-2.fyi.app/external` |
Override with `FYI_BASE_URL` if needed. Copy `.env.example` to `.env` for local development.
## Local setup
```bash
bun install
cp .env.example .env # fill in FYI credentials
bun run dev # watch mode
# or
bun start
```
- Health: `http://localhost:3000/health`
- MCP: `http://localhost:3000/mcp`
## Railway
This repo is connected to Railway. Deploys follow GitHub pushes.
Config is in `railway.toml`:
- Install: `bun install --frozen-lockfile`
- Start: `bun run src/index.ts`
- Health check: `/health`
Set secrets in Railway (do not commit them):
```bash
railway variables set FYI_ACCESS_ID=... FYI_ACCESS_SECRET=... FYI_REGION=uk MCP_API_KEY=...
```
Optional Dockerfile (`oven/bun:1`) is included if you prefer image-based builds.
### Authentication (API key only)
No OAuth. `/mcp` requires the shared `MCP_API_KEY` via header:
- `Authorization: Bearer <MCP_API_KEY>`
- or `x-api-key: <MCP_API_KEY>`
`/health` stays public for Railway health checks.
```json
{
"mcpServers": {
"fyi-docs": {
"url": "https://fyi-mcp-production.up.railway.app/mcp",
"headers": {
"Authorization": "Bearer <MCP_API_KEY>"
}
}
}
}
```
**Grok Build / CLI:**
```toml
[mcp_servers.fyi-docs]
url = "https://fyi-mcp-production.up.railway.app/mcp"
headers = { "Authorization" = "Bearer <MCP_API_KEY>" }
```
> **Note:** Hosts that only support OAuth custom connectors (e.g. Grok.com web)
> cannot connect to this server. Use clients that accept a static Authorization header.
## Scripts
| Script | Command |
|--------|---------|
| `bun start` | Run server |
| `bun run dev` | Run with `--watch` |
| `bun run typecheck` | `tsc --noEmit` |
| `bun run build` | Bundle to `dist/` |
## Project layout
```
src/
index.ts # Bun HTTP entry (/health, /mcp)
server.ts # MCP server + tool registration
fyi/
client.ts # FYI External API client
config.ts # Env validation (Zod)
types.ts
tools/
documents.ts
clients.ts
jobs.ts
tasks.ts
cabinets.ts
connection.ts
utils/
response.ts # Summaries + safe errors
```
## Security
- No secrets in source or logs
- Fail-fast on missing `FYI_ACCESS_ID` / `FYI_ACCESS_SECRET` / `MCP_API_KEY`
- `/mcp` protected by shared API key only (no OAuth)
- Read-only tools for v1
- Sensitive keys redacted from tool output
## Out of scope (v1)
OAuth, write/upsert operations, binary document download, custom domain, persistent storage.
## License
Private / unlicensed unless stated otherwise.
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessSyncing