mirror of
https://github.com/AmruthPillai/Reactive-Resume.git
synced 2026-06-22 04:11:55 +10:00
Fix MCP tool names for Claude Desktop incompatibility (#2885)
* fixes #2884, rename tool names for claude to work * update dependencies
This commit is contained in:
@@ -207,25 +207,29 @@ If you're running a self-hosted Reactive Resume instance, replace `https://rxres
|
||||
|
||||
## Available Tools
|
||||
|
||||
Tool names use a hierarchical `reactive_resume.*` prefix ([SEP-986](https://github.com/modelcontextprotocol/modelcontextprotocol/issues/986) style) so they stay distinct when multiple MCP servers are enabled in the same client.
|
||||
Tool names use a `reactive_resume_` prefix so they stay distinct when multiple MCP servers are enabled in the same client.
|
||||
|
||||
| Tool | Description |
|
||||
| --------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `reactive_resume.list_resumes` | List all resumes with IDs, names, tags, and status. Supports filtering by tags and sorting by last updated, creation date, or name |
|
||||
| `reactive_resume.get_resume` | Get the full data of a specific resume by ID |
|
||||
| `reactive_resume.create_resume` | Create a new, empty resume with a name and slug. Optionally pre-fill with sample data |
|
||||
| `reactive_resume.duplicate_resume` | Create a copy of an existing resume with a new name and slug |
|
||||
| `reactive_resume.patch_resume` | Apply JSON Patch (RFC 6902) operations to modify a resume's data |
|
||||
| `reactive_resume.delete_resume` | Permanently delete a resume and all associated files. **Irreversible** |
|
||||
| `reactive_resume.lock_resume` | Lock a resume to prevent edits, patches, and deletion |
|
||||
| `reactive_resume.unlock_resume` | Unlock a previously locked resume to re-enable editing |
|
||||
| `reactive_resume.export_resume_pdf` | Generate a PDF from the resume and return a download URL |
|
||||
| `reactive_resume.get_resume_screenshot` | Get a visual preview of the resume's first page as a WebP image URL |
|
||||
| `reactive_resume.get_resume_statistics` | Get view and download statistics for a resume |
|
||||
| `reactive_resume_list_resumes` | List all resumes with IDs, names, tags, and status. Supports filtering by tags and sorting by last updated, creation date, or name |
|
||||
| `reactive_resume_list_resume_tags` | List every distinct tag in use across your resumes (sorted) |
|
||||
| `reactive_resume_get_resume` | Get the full data of a specific resume by ID |
|
||||
| `reactive_resume_get_resume_analysis` | Get the latest saved AI analysis for a resume (from the web app), if any |
|
||||
| `reactive_resume_create_resume` | Create a new, empty resume with a name and slug. Optionally pre-fill with sample data |
|
||||
| `reactive_resume_import_resume` | Create a resume from a full ResumeData JSON export (random name/slug). Large files may exceed client limits |
|
||||
| `reactive_resume_duplicate_resume` | Create a copy of an existing resume with a new name and slug |
|
||||
| `reactive_resume_patch_resume` | Apply JSON Patch (RFC 6902) operations to modify a resume's data |
|
||||
| `reactive_resume_update_resume` | Update metadata only: name, slug, tags, `isPublic`. Returns canonical share URL; passwords are not managed via MCP |
|
||||
| `reactive_resume_delete_resume` | Permanently delete a resume and all associated files. **Irreversible** |
|
||||
| `reactive_resume_lock_resume` | Lock a resume to prevent edits, patches, and deletion |
|
||||
| `reactive_resume_unlock_resume` | Unlock a previously locked resume to re-enable editing |
|
||||
| `reactive_resume_export_resume_pdf` | Generate a PDF from the resume and return a download URL |
|
||||
| `reactive_resume_get_resume_screenshot` | Get a visual preview of the resume's first page as a WebP image URL |
|
||||
| `reactive_resume_get_resume_statistics` | Get view and download statistics for a resume |
|
||||
|
||||
### Breaking change (tool names)
|
||||
|
||||
Older clients may refer to unprefixed names (`list_resumes`, `get_resume`, …). Those names are no longer used; update automations and saved prompts to the `reactive_resume.*` names above.
|
||||
Older clients may refer to unprefixed names (`list_resumes`, `get_resume`, …) or dot-separated names (`reactive_resume.list_resumes`, …). Those names are no longer used; update automations and saved prompts to the `reactive_resume_*` names above.
|
||||
|
||||
## Available Resources
|
||||
|
||||
@@ -235,12 +239,12 @@ Resources follow MCP conventions: **static** items appear in `resources/list`; *
|
||||
| ------------------------------------- | --------------------------------------------------------------------------------------------- |
|
||||
| `resources/list` | Static resources only — currently **`resume://_meta/schema`** (ResumeData JSON Schema) |
|
||||
| `resources/templates/list` | **`resume://{id}`** — template for reading full resume JSON by ID (not enumerated per resume) |
|
||||
| `reactive_resume.list_resumes` (tool) | **Primary way to discover resume IDs** — resumes are not listed as separate MCP resources |
|
||||
| `reactive_resume_list_resumes` (tool) | **Primary way to discover resume IDs** — resumes are not listed as separate MCP resources |
|
||||
|
||||
| URI | Description |
|
||||
| ----------------------- | ------------------------------------------------------------------------ |
|
||||
| `resume://_meta/schema` | ResumeData JSON Schema — use for valid JSON Patch paths and value types |
|
||||
| `resume://{id}` | Full resume data as JSON — use an ID from `reactive_resume.list_resumes` |
|
||||
| `resume://{id}` | Full resume data as JSON — use an ID from `reactive_resume_list_resumes` |
|
||||
|
||||
### Breaking change (schema URI)
|
||||
|
||||
@@ -275,7 +279,10 @@ Once your MCP client is connected, you can use natural language to interact with
|
||||
### Creating & Managing
|
||||
|
||||
- "Create a new resume called 'Frontend Engineer 2026'"
|
||||
- "Import this exported ResumeData JSON as a new resume"
|
||||
- "What tags do I use across my resumes?"
|
||||
- "Duplicate my 'Software Engineer' resume for a product manager role"
|
||||
- "Make my resume public and give me the share link"
|
||||
- "Lock my finalized resume so it can't be accidentally edited"
|
||||
- "Delete my old draft resume"
|
||||
|
||||
@@ -306,8 +313,9 @@ Once your MCP client is connected, you can use natural language to interact with
|
||||
- "Tailor my resume for this job description: ..." (uses `tailor_resume`)
|
||||
|
||||
<Tip>
|
||||
The AI will use `reactive_resume.get_resume` to inspect your current resume before making changes with
|
||||
`reactive_resume.patch_resume`. This ensures the correct JSON paths are used.
|
||||
The AI will use `reactive_resume_get_resume` to inspect your current resume before making changes with
|
||||
`reactive_resume_patch_resume`. This ensures the correct JSON paths are used. Use `reactive_resume_update_resume` for
|
||||
name, slug, tags, and public visibility (not for section content).
|
||||
</Tip>
|
||||
|
||||
## Troubleshooting
|
||||
@@ -317,7 +325,7 @@ Once your MCP client is connected, you can use natural language to interact with
|
||||
| "Unauthorized" with no login prompt | Your client may not support MCP OAuth discovery. Use API key mode (`x-api-key`) |
|
||||
| OAuth login opens but fails redirect/callback | Confirm your client's MCP OAuth callback settings and retry the connection |
|
||||
| "API error (401)" | Your API key is invalid or expired. Create a new one in **Settings → API Keys** |
|
||||
| "API error (404)" | The resume ID doesn't exist. Use `reactive_resume.list_resumes` to find valid IDs |
|
||||
| "API error (404)" | The resume ID doesn't exist. Use `reactive_resume_list_resumes` to find valid IDs |
|
||||
| "API error (403)" | The resume is locked. Unlock it in the Reactive Resume dashboard |
|
||||
| Connection refused | Check that the URL is correct and the instance is running |
|
||||
| "ReferenceError: File is not defined" when using `mcp-remote` | You're running Node.js 18. `mcp-remote` requires **Node.js 20 or later** — upgrade with `nvm use 20` or `nvm alias default 20` |
|
||||
|
||||
+9
-9
@@ -53,17 +53,17 @@
|
||||
"@lingui/react": "^5.9.5",
|
||||
"@modelcontextprotocol/sdk": "^1.29.0",
|
||||
"@monaco-editor/react": "4.8.0-rc.3",
|
||||
"@orpc/client": "^1.13.13",
|
||||
"@orpc/json-schema": "^1.13.13",
|
||||
"@orpc/openapi": "^1.13.13",
|
||||
"@orpc/server": "^1.13.13",
|
||||
"@orpc/tanstack-query": "^1.13.13",
|
||||
"@orpc/zod": "^1.13.13",
|
||||
"@orpc/client": "^1.13.14",
|
||||
"@orpc/json-schema": "^1.13.14",
|
||||
"@orpc/openapi": "^1.13.14",
|
||||
"@orpc/server": "^1.13.14",
|
||||
"@orpc/tanstack-query": "^1.13.14",
|
||||
"@orpc/zod": "^1.13.14",
|
||||
"@phosphor-icons/react": "^2.1.10",
|
||||
"@phosphor-icons/web": "^2.1.2",
|
||||
"@sindresorhus/slugify": "^3.0.0",
|
||||
"@t3-oss/env-core": "^0.13.11",
|
||||
"@tanstack/react-query": "^5.96.2",
|
||||
"@tanstack/react-query": "^5.97.0",
|
||||
"@tanstack/react-router": "^1.168.10",
|
||||
"@tanstack/react-router-ssr-query": "^1.166.10",
|
||||
"@tanstack/react-start": "^1.167.16",
|
||||
@@ -138,9 +138,9 @@
|
||||
"@types/pg": "^8.20.0",
|
||||
"@types/react": "^19.2.14",
|
||||
"@types/react-dom": "^19.2.3",
|
||||
"@typescript/native-preview": "7.0.0-dev.20260408.1",
|
||||
"@typescript/native-preview": "7.0.0-dev.20260409.1",
|
||||
"@vitejs/plugin-react": "^6.0.1",
|
||||
"@vitest/coverage-v8": "^4.1.3",
|
||||
"@vitest/coverage-v8": "^4.1.4",
|
||||
"babel-plugin-macros": "^3.1.0",
|
||||
"drizzle-kit": "1.0.0-beta.21",
|
||||
"happy-dom": "^20.8.9",
|
||||
|
||||
Generated
+182
-182
@@ -77,23 +77,23 @@ importers:
|
||||
specifier: 4.8.0-rc.3
|
||||
version: 4.8.0-rc.3(monaco-editor@0.55.1)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)
|
||||
'@orpc/client':
|
||||
specifier: ^1.13.13
|
||||
version: 1.13.13(@opentelemetry/api@1.9.0)
|
||||
specifier: ^1.13.14
|
||||
version: 1.13.14(@opentelemetry/api@1.9.0)
|
||||
'@orpc/json-schema':
|
||||
specifier: ^1.13.13
|
||||
version: 1.13.13(@opentelemetry/api@1.9.0)(crossws@0.4.4(srvx@0.11.15))(ws@8.20.0)
|
||||
specifier: ^1.13.14
|
||||
version: 1.13.14(@opentelemetry/api@1.9.0)(crossws@0.4.4(srvx@0.11.15))(ws@8.20.0)
|
||||
'@orpc/openapi':
|
||||
specifier: ^1.13.13
|
||||
version: 1.13.13(@opentelemetry/api@1.9.0)(crossws@0.4.4(srvx@0.11.15))(ws@8.20.0)
|
||||
specifier: ^1.13.14
|
||||
version: 1.13.14(@opentelemetry/api@1.9.0)(crossws@0.4.4(srvx@0.11.15))(ws@8.20.0)
|
||||
'@orpc/server':
|
||||
specifier: ^1.13.13
|
||||
version: 1.13.13(@opentelemetry/api@1.9.0)(crossws@0.4.4(srvx@0.11.15))(ws@8.20.0)
|
||||
specifier: ^1.13.14
|
||||
version: 1.13.14(@opentelemetry/api@1.9.0)(crossws@0.4.4(srvx@0.11.15))(ws@8.20.0)
|
||||
'@orpc/tanstack-query':
|
||||
specifier: ^1.13.13
|
||||
version: 1.13.13(@opentelemetry/api@1.9.0)(@orpc/client@1.13.13(@opentelemetry/api@1.9.0))(@tanstack/query-core@5.96.2)
|
||||
specifier: ^1.13.14
|
||||
version: 1.13.14(@opentelemetry/api@1.9.0)(@orpc/client@1.13.14(@opentelemetry/api@1.9.0))(@tanstack/query-core@5.97.0)
|
||||
'@orpc/zod':
|
||||
specifier: ^1.13.13
|
||||
version: 1.13.13(@opentelemetry/api@1.9.0)(@orpc/contract@1.13.13(@opentelemetry/api@1.9.0))(@orpc/server@1.13.13(@opentelemetry/api@1.9.0)(crossws@0.4.4(srvx@0.11.15))(ws@8.20.0))(crossws@0.4.4(srvx@0.11.15))(ws@8.20.0)(zod@4.3.6)
|
||||
specifier: ^1.13.14
|
||||
version: 1.13.14(@opentelemetry/api@1.9.0)(@orpc/contract@1.13.14(@opentelemetry/api@1.9.0))(@orpc/server@1.13.14(@opentelemetry/api@1.9.0)(crossws@0.4.4(srvx@0.11.15))(ws@8.20.0))(crossws@0.4.4(srvx@0.11.15))(ws@8.20.0)(zod@4.3.6)
|
||||
'@phosphor-icons/react':
|
||||
specifier: ^2.1.10
|
||||
version: 2.1.10(react-dom@19.2.5(react@19.2.5))(react@19.2.5)
|
||||
@@ -107,14 +107,14 @@ importers:
|
||||
specifier: ^0.13.11
|
||||
version: 0.13.11(typescript@5.9.3)(valibot@1.2.0(typescript@5.9.3))(zod@4.3.6)
|
||||
'@tanstack/react-query':
|
||||
specifier: ^5.96.2
|
||||
version: 5.96.2(react@19.2.5)
|
||||
specifier: ^5.97.0
|
||||
version: 5.97.0(react@19.2.5)
|
||||
'@tanstack/react-router':
|
||||
specifier: ^1.168.10
|
||||
version: 1.168.10(react-dom@19.2.5(react@19.2.5))(react@19.2.5)
|
||||
'@tanstack/react-router-ssr-query':
|
||||
specifier: ^1.166.10
|
||||
version: 1.166.10(@tanstack/query-core@5.96.2)(@tanstack/react-query@5.96.2(react@19.2.5))(@tanstack/react-router@1.168.10(react-dom@19.2.5(react@19.2.5))(react@19.2.5))(@tanstack/router-core@1.168.9)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)
|
||||
version: 1.166.10(@tanstack/query-core@5.97.0)(@tanstack/react-query@5.97.0(react@19.2.5))(@tanstack/react-router@1.168.10(react-dom@19.2.5(react@19.2.5))(react@19.2.5))(@tanstack/router-core@1.168.9)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)
|
||||
'@tanstack/react-start':
|
||||
specifier: ^1.167.16
|
||||
version: 1.167.16(@voidzero-dev/vite-plus-core@0.1.16(@types/node@25.5.2)(jiti@2.6.1)(terser@5.46.1)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.3))(crossws@0.4.4(srvx@0.11.15))(react-dom@19.2.5(react@19.2.5))(react@19.2.5)
|
||||
@@ -327,14 +327,14 @@ importers:
|
||||
specifier: ^19.2.3
|
||||
version: 19.2.3(@types/react@19.2.14)
|
||||
'@typescript/native-preview':
|
||||
specifier: 7.0.0-dev.20260408.1
|
||||
version: 7.0.0-dev.20260408.1
|
||||
specifier: 7.0.0-dev.20260409.1
|
||||
version: 7.0.0-dev.20260409.1
|
||||
'@vitejs/plugin-react':
|
||||
specifier: ^6.0.1
|
||||
version: 6.0.1(@rolldown/plugin-babel@0.2.2(@babel/core@7.29.0)(@babel/runtime@7.29.2)(@voidzero-dev/vite-plus-core@0.1.16(@types/node@25.5.2)(jiti@2.6.1)(terser@5.46.1)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.3))(rolldown@1.0.0-rc.15))(@voidzero-dev/vite-plus-core@0.1.16(@types/node@25.5.2)(jiti@2.6.1)(terser@5.46.1)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.3))
|
||||
'@vitest/coverage-v8':
|
||||
specifier: ^4.1.3
|
||||
version: 4.1.3(@voidzero-dev/vite-plus-test@0.1.16(@opentelemetry/api@1.9.0)(@types/node@25.5.2)(@voidzero-dev/vite-plus-core@0.1.16(@types/node@25.5.2)(jiti@2.6.1)(terser@5.46.1)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.3))(happy-dom@20.8.9)(jiti@2.6.1)(jsdom@29.0.1(@noble/hashes@2.0.1))(terser@5.46.1)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.3))
|
||||
specifier: ^4.1.4
|
||||
version: 4.1.4(@voidzero-dev/vite-plus-test@0.1.16(@opentelemetry/api@1.9.0)(@types/node@25.5.2)(@voidzero-dev/vite-plus-core@0.1.16(@types/node@25.5.2)(jiti@2.6.1)(terser@5.46.1)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.3))(happy-dom@20.8.9)(jiti@2.6.1)(jsdom@29.0.1(@noble/hashes@2.0.1))(terser@5.46.1)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.3))
|
||||
babel-plugin-macros:
|
||||
specifier: ^3.1.0
|
||||
version: 3.1.0
|
||||
@@ -2197,26 +2197,26 @@ packages:
|
||||
resolution: {integrity: sha512-cifvXDhcqMwwTlTK04GBNeIe7yyo28Mfby85QXFe1Yk8nmi36Ab/5UQwptOx84SsoGNRg+EVSjwzfSZMy6pmlw==}
|
||||
engines: {node: '>=14'}
|
||||
|
||||
'@orpc/client@1.13.13':
|
||||
resolution: {integrity: sha512-jagx/Sa+9K4HEC5lBrUlMSrmR/06hvZctWh93/sKZc8GBk4zM0+71oT1kXQVw1oRYFV2XAq3xy3m6NdM6gfKYA==}
|
||||
'@orpc/client@1.13.14':
|
||||
resolution: {integrity: sha512-JQf3lO//UGHmmkd8+9fuWuh1gga1lhWuKnsT19cui7F6WizBy0NdFSVQerOsSy2c1kxOthlD7GnicGgSY2rhQA==}
|
||||
|
||||
'@orpc/contract@1.13.13':
|
||||
resolution: {integrity: sha512-md6iyrYkePBSJNs1VnVEEnAUORMDPHIf3JGRSHxyssIcNakev/iOjP0HvpH0Sx0MlTBhihAJo6uFL8Vpth58Nw==}
|
||||
'@orpc/contract@1.13.14':
|
||||
resolution: {integrity: sha512-MfsjaQQDVcs4wHmdl5N/7vkwMnQ41nlojWXyRfRXNJHQczqBzM6sYaTJuUPXlw4YbIu64KHZ5nbbtwNCO5YXsg==}
|
||||
|
||||
'@orpc/interop@1.13.13':
|
||||
resolution: {integrity: sha512-S8edIRA7ekD3/gHx5MrsO9CxZ0QvCaVDkVbNf42SZbLYPXuvxtdH0CYwaB1q9uQg2Jk0PBP8AquLH6WFwjMSbQ==}
|
||||
'@orpc/interop@1.13.14':
|
||||
resolution: {integrity: sha512-7umABTBzQMNTX8dTKrbIOu9g5XJuMeqijC6Gu6jlaVP90e8D57n7Zv6HfwSgPVq0oQXf9n/ENptzVj3TpxpXsQ==}
|
||||
|
||||
'@orpc/json-schema@1.13.13':
|
||||
resolution: {integrity: sha512-48CgMrWIKG/t8l4OBlFRcYOj2ZCrIXfw1LA2Q6qRGdyBPzSLmQCMhh3Y4eoFXfz/wKvQIfyoUmBIdd91BxSyLg==}
|
||||
'@orpc/json-schema@1.13.14':
|
||||
resolution: {integrity: sha512-BLGewxG0dv5AhLEwTmeXDNZ0PiRxvCzxcUtbo8FExwIR6wpknfWukeoymaHn8vtyfuOO9nvPfertNuNUReiufg==}
|
||||
|
||||
'@orpc/openapi-client@1.13.13':
|
||||
resolution: {integrity: sha512-k8od+bD7MqysKPPybAkxgfaNIaNseFPXtbidWkZAdCZ5w34SnDc7QPZJ0PQbyt9n9B+jOXSADNwQSTWSuGpjyA==}
|
||||
'@orpc/openapi-client@1.13.14':
|
||||
resolution: {integrity: sha512-mHuj/UL5qLqB1JqrRdlAoUYMidbsry8Cr9QOlOZk1mp7+OZhasFv75UNzxyjNNaSjyd3l2k4UkgpcHK4VSD7tQ==}
|
||||
|
||||
'@orpc/openapi@1.13.13':
|
||||
resolution: {integrity: sha512-lm3cAR1KJ1xp5WyDKCIqvhzYlDC914oevwYPWC7GFvTU1cTEmFP4lkQRdzLfvo06BprCg+UtHjzdLUDrBOF/zQ==}
|
||||
'@orpc/openapi@1.13.14':
|
||||
resolution: {integrity: sha512-wwfq8CwOTxuNOfamHKTrXgUxxAhh8WSTpu2OgZhNDWxH0p6V/xLhlXl2iSjmzyO4QuBpE26fchDwaVAGic9zlQ==}
|
||||
|
||||
'@orpc/server@1.13.13':
|
||||
resolution: {integrity: sha512-l3OfiaqfLiLQqamXufKiEzT8K9Zq8VHvijADV5eDJOaz6sFzK1Mg6q2D8l9wcmuyG7ga0HfMT+cf3JQsh5WDIA==}
|
||||
'@orpc/server@1.13.14':
|
||||
resolution: {integrity: sha512-bF+sNbSHBgs1uwzHXgTxcxWIG42ryX+w32l+FJRHrAmGma+S8PmS1X2HZ/J7XycyYVBJMUUzBr8M88pP+UcdxQ==}
|
||||
peerDependencies:
|
||||
crossws: '>=0.3.4'
|
||||
ws: '>=8.18.1'
|
||||
@@ -2226,48 +2226,48 @@ packages:
|
||||
ws:
|
||||
optional: true
|
||||
|
||||
'@orpc/shared@1.13.13':
|
||||
resolution: {integrity: sha512-kNpYOBjHvmgKHla6munWOaEeA0utEfAvoiZpXjiRjjt1RxTibdwQvVHgxRIBNMXfQsb+ON3Q/wDkoaUhvvSnIw==}
|
||||
'@orpc/shared@1.13.14':
|
||||
resolution: {integrity: sha512-/ri8ttSX+ppoo01d3LdqQ4Xh6VZS5PYRYmHxTvO8tuyiqBJhN18d8P1VtEW4T9hetoK7JZKeU7EAeqVUnCF9WA==}
|
||||
peerDependencies:
|
||||
'@opentelemetry/api': '>=1.9.0'
|
||||
peerDependenciesMeta:
|
||||
'@opentelemetry/api':
|
||||
optional: true
|
||||
|
||||
'@orpc/standard-server-aws-lambda@1.13.13':
|
||||
resolution: {integrity: sha512-e7310DnN6FSpRgR5gQpwvwg2B3uR+NoT7qlnyQWsjxQGr95L4GST3hRNSsQdQyXmFx1jvCCp0i3kAE9SJyvU6A==}
|
||||
'@orpc/standard-server-aws-lambda@1.13.14':
|
||||
resolution: {integrity: sha512-5P1ZzgS6zKTjjI0SaCgMlTF5PM4dbOlmP2Zm2Lh1ool/iNvjMzXSb86pbKrWOo5/V8dzn4GMyCgNso9za1nUMg==}
|
||||
|
||||
'@orpc/standard-server-fastify@1.13.13':
|
||||
resolution: {integrity: sha512-G5Sq+rZDPwHvWJHsAA6bYWoJ7LcGyBby+SjjEGwz+viRdBk/inZnZafKpM+pL89aDdq6iw99Bcbug5WFPP6KdA==}
|
||||
'@orpc/standard-server-fastify@1.13.14':
|
||||
resolution: {integrity: sha512-DcgL5UFjHENGj1gWiQig4iObMNnnw8z7UrfTELTCejQ9NAWE8aGYdx4bZ/hk4JkieLJ+9aosGK57di6xXBtvPA==}
|
||||
peerDependencies:
|
||||
fastify: '>=5.6.1'
|
||||
peerDependenciesMeta:
|
||||
fastify:
|
||||
optional: true
|
||||
|
||||
'@orpc/standard-server-fetch@1.13.13':
|
||||
resolution: {integrity: sha512-Lffy26+WtCQkwOUacsrdyeJF1GNzrhm75O3LXKVFXqmSdyVVdyI6zuqLn/YKGODU2L9IqGxZ2CwsV2tE298SSA==}
|
||||
'@orpc/standard-server-fetch@1.13.14':
|
||||
resolution: {integrity: sha512-k2zkCi98qd3NkvWhUX/Yece/qjB+o07g/gHC509YB5HbOGtBV/da3eseYjFyzBx5LDxMz28BOALI8/q/YDhKZw==}
|
||||
|
||||
'@orpc/standard-server-node@1.13.13':
|
||||
resolution: {integrity: sha512-wI45h/bVWn7lgvqqm5aM7vj5BblmmBdFG2wbEhmpY85DslbCtMNJrIw/x+zxm1XgYAzsKLExLp6L01hzjeHmEA==}
|
||||
'@orpc/standard-server-node@1.13.14':
|
||||
resolution: {integrity: sha512-GKMWfMuKX+dycpEFMoFrGY+zhZMKPoR9HSM66Ebn/ixr2qCVfQaoudPa9MAgP+fv/ctZx+nkt1rR7esUFMdMAg==}
|
||||
|
||||
'@orpc/standard-server-peer@1.13.13':
|
||||
resolution: {integrity: sha512-FeWAbXfnZDPYQRajM0hD6GJvHeC3DZILngAjdcLHy5zt3riu6nL2lLPSWDv5yNWWscmYU+CfKmXWd0Z01BOeWA==}
|
||||
'@orpc/standard-server-peer@1.13.14':
|
||||
resolution: {integrity: sha512-jinseQ8bn7XQOHjsCXhR1HiF3wAwn1xEQPpnE/av0PoOi4h0ATvhZjDLaRHvRavs8YwrIqwSuAuYT/hDxON58A==}
|
||||
|
||||
'@orpc/standard-server@1.13.13':
|
||||
resolution: {integrity: sha512-9pgS8XvauuRQElkyuD8F3om+nN0KBEnTkhblDHCBzkZERjWkmfirJmshQrWHoFaDTk+nnXHIaY6d7TBTxXdPRw==}
|
||||
'@orpc/standard-server@1.13.14':
|
||||
resolution: {integrity: sha512-o8PaDERiwREFQpIZO0mQ1PhguchyNzrf1w7m3eK1JB4rPjHu1VJUgqCpy/sV3Id5ji4bX/gKHEC3NZjDX6mEWQ==}
|
||||
|
||||
'@orpc/tanstack-query@1.13.13':
|
||||
resolution: {integrity: sha512-6+Cheaiu+RDPdszdeRKoBINrF8MQp64zSeZB+L3gqgF43zlYDhLOgELZMzYa6U3U6bLk4rmIeubpk+i1kACfRg==}
|
||||
'@orpc/tanstack-query@1.13.14':
|
||||
resolution: {integrity: sha512-5rq1Z1anVTVBseYeNBi5RJSgWPxpD0MqK7MYej3xnt56jjc6mFmWpUGNz9xy0BXPh3KmA/xDTNuB23kKgJ5JmQ==}
|
||||
peerDependencies:
|
||||
'@orpc/client': 1.13.13
|
||||
'@orpc/client': 1.13.14
|
||||
'@tanstack/query-core': '>=5.80.2'
|
||||
|
||||
'@orpc/zod@1.13.13':
|
||||
resolution: {integrity: sha512-K2iWGHopi3apExqNVb6EWJJqmq7cgytY3PjJyJ/Uy98UfJJ17Kwz7rAZKffNc7E967rNk9IH8MIcUcGkT7dmzQ==}
|
||||
'@orpc/zod@1.13.14':
|
||||
resolution: {integrity: sha512-lpF8Nyb+WdW0PieZcJB3KvKztGveXvckOqXMyWTWvyrylV3rCPmeUneVQghjZOLqJdAevo4jqV2/BgHWSt3EEA==}
|
||||
peerDependencies:
|
||||
'@orpc/contract': 1.13.13
|
||||
'@orpc/server': 1.13.13
|
||||
'@orpc/contract': 1.13.14
|
||||
'@orpc/server': 1.13.14
|
||||
zod: '>=3.25.0'
|
||||
|
||||
'@oxc-parser/binding-android-arm-eabi@0.121.0':
|
||||
@@ -3582,11 +3582,11 @@ packages:
|
||||
resolution: {integrity: sha512-NaOGLRrddszbQj9upGat6HG/4TKvXLvu+osAIgfxPYA+eIvYKv8GKDJOrY2D3/U9MRnKfMWD7bU4jeD4xmqyIg==}
|
||||
engines: {node: '>=20.19'}
|
||||
|
||||
'@tanstack/query-core@5.96.2':
|
||||
resolution: {integrity: sha512-hzI6cTVh4KNRk8UtoIBS7Lv9g6BnJPXvBKsvYH1aGWvv0347jT3BnSvztOE+kD76XGvZnRC/t6qdW1CaIfwCeA==}
|
||||
'@tanstack/query-core@5.97.0':
|
||||
resolution: {integrity: sha512-QdpLP5VzVMgo4VtaPppRA2W04UFjIqX+bxke/ZJhE5cfd5UPkRzqIAJQt9uXkQJjqE8LBOMbKv7f8HCsZltXlg==}
|
||||
|
||||
'@tanstack/react-query@5.96.2':
|
||||
resolution: {integrity: sha512-sYyzzJT4G0g02azzJ8o55VFFV31XvFpdUpG+unxS0vSaYsJnSPKGoI6WdPwUucJL1wpgGfwfmntNX/Ub1uOViA==}
|
||||
'@tanstack/react-query@5.97.0':
|
||||
resolution: {integrity: sha512-y4So4eGcQoK2WVMAcDNZE9ofB/p5v1OlKvtc1F3uqHwrtifobT7q+ZnXk2mRkc8E84HKYSlAE9z6HXl2V0+ySQ==}
|
||||
peerDependencies:
|
||||
react: ^18 || ^19
|
||||
|
||||
@@ -4026,43 +4026,43 @@ packages:
|
||||
'@types/yauzl@2.10.3':
|
||||
resolution: {integrity: sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==}
|
||||
|
||||
'@typescript/native-preview-darwin-arm64@7.0.0-dev.20260408.1':
|
||||
resolution: {integrity: sha512-YcPczNLfPDB13eUBYHkTOkL7HyWqqqEhho4eSxhAvigZuxvtHQ1uyILIvLVAwipEVzhJ8QciKmLdLucpfi4XyA==}
|
||||
'@typescript/native-preview-darwin-arm64@7.0.0-dev.20260409.1':
|
||||
resolution: {integrity: sha512-GcRRnaoeZVrbC47woQ/2t3vPoQcTSjsWPEAQGtwNSdw7Z9TKxG4ES22ghJIQXd3ncTRCMJ+XELnnuqxVutkJ9w==}
|
||||
cpu: [arm64]
|
||||
os: [darwin]
|
||||
|
||||
'@typescript/native-preview-darwin-x64@7.0.0-dev.20260408.1':
|
||||
resolution: {integrity: sha512-cHqkDg53xxxz21MThLBf4vx1kyIpRPEYNdEiQlvu9O35Tth49+aub6F+/YEMd9MG4TYZmxh1bEjkjErTUIElpA==}
|
||||
'@typescript/native-preview-darwin-x64@7.0.0-dev.20260409.1':
|
||||
resolution: {integrity: sha512-7s8DXAa0Xpu/8PEjYIc4I36Ju7eVpoz9k3E+3WQdOF8pIPWYohiOj+zi68m9XYQck+rnkjUFo26ThVKqVetoMA==}
|
||||
cpu: [x64]
|
||||
os: [darwin]
|
||||
|
||||
'@typescript/native-preview-linux-arm64@7.0.0-dev.20260408.1':
|
||||
resolution: {integrity: sha512-iHG0FEXq/QFsn+qlTPllxdcbvfQ9aRYggy4lc1z0+f11Nyk4YDNCSiR8WW7pbnOTx/VreGbbXhlpuJXTidqL8g==}
|
||||
'@typescript/native-preview-linux-arm64@7.0.0-dev.20260409.1':
|
||||
resolution: {integrity: sha512-cGTzTUqRGlIDwdtkDy6qTrvrqpe27W4CdgnFn0FpxpiWnaIi3wqjlzQ1grtqrqainw/yuPy5hn/I86sQgN6nvA==}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
|
||||
'@typescript/native-preview-linux-arm@7.0.0-dev.20260408.1':
|
||||
resolution: {integrity: sha512-w26Gv9yq9LIYIhxjkQC+i0wBPDdQdX+H06ZhyVRL5grKWTIsk9Xwjp9mDRB/dGlXBKcvnM25JH16OyAA0rFH3A==}
|
||||
'@typescript/native-preview-linux-arm@7.0.0-dev.20260409.1':
|
||||
resolution: {integrity: sha512-fOa07JBUXQpEPq+024g346inYZ2xp63ELuoRq6J0jwDWQ/ftCCuvdQNMncwFhsm1qlMdKT3S68NrnSxX16hiaw==}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
|
||||
'@typescript/native-preview-linux-x64@7.0.0-dev.20260408.1':
|
||||
resolution: {integrity: sha512-hMcUlUIzYbvbdq6j/B4RPL+kZR917NGnE9AgPZ7dJ92yamH/7LGT1Mnlc6McUx31yqTFBFHdTc7Cfx+ynua7Iw==}
|
||||
'@typescript/native-preview-linux-x64@7.0.0-dev.20260409.1':
|
||||
resolution: {integrity: sha512-lQrbc/BJKBxQrR1ttBDU5sYY1Hb2moFQgHL20T6nbapNqGpK4pzy64p+NK39O93D4omiCSk04pkchBCVrMPSAg==}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
|
||||
'@typescript/native-preview-win32-arm64@7.0.0-dev.20260408.1':
|
||||
resolution: {integrity: sha512-avJWIEKSx4rdBLZD1FOOTuxTU51dQfYb3jZvZMaXD4thJjq+6eSwfzu2elwL36AZDlnaxggGjB5nBxp0t54iOA==}
|
||||
'@typescript/native-preview-win32-arm64@7.0.0-dev.20260409.1':
|
||||
resolution: {integrity: sha512-kmCafMo1xZlYx+9WnfpeZJ2tnB/CcJdR8QPX7j9vqcpe51D7b7Intmr921dD48KGpVh5YgjQ1MEFE5mjGqGMaA==}
|
||||
cpu: [arm64]
|
||||
os: [win32]
|
||||
|
||||
'@typescript/native-preview-win32-x64@7.0.0-dev.20260408.1':
|
||||
resolution: {integrity: sha512-gpvEHkF/WoxkA3711c4uWNCZO9WAuwrq49COdNwxgOTzYHnMc1yCj8CpkCUJwU0f/Ydwp2s6/efn6gTMvtckPg==}
|
||||
'@typescript/native-preview-win32-x64@7.0.0-dev.20260409.1':
|
||||
resolution: {integrity: sha512-WRd+JpQipTsE15QgYr3w7J0f1NKvGcq2QEgmcq8hB0WZA1X2WhQopNu+MpPQ3tdDD42VjMhm8ZoB8HpuOoXK5w==}
|
||||
cpu: [x64]
|
||||
os: [win32]
|
||||
|
||||
'@typescript/native-preview@7.0.0-dev.20260408.1':
|
||||
resolution: {integrity: sha512-N0MZLEUnAoP/aRVk7MY119LDsESkbtEwIw+YeXi/jjx2XCqf7ni3GxIVsUYtf/troyuSedq3V/OUrkoCh5A9gA==}
|
||||
'@typescript/native-preview@7.0.0-dev.20260409.1':
|
||||
resolution: {integrity: sha512-CV1HEMGo1xCySwUJbCQOF+mmrTue8KTJ1Od2kKWhcbOpu8fPBfaqIpbAM6tGLcNEykEjMMTYHc/VTLbMgxdScQ==}
|
||||
hasBin: true
|
||||
|
||||
'@typespec/ts-http-runtime@0.3.5':
|
||||
@@ -4126,20 +4126,20 @@ packages:
|
||||
babel-plugin-react-compiler:
|
||||
optional: true
|
||||
|
||||
'@vitest/coverage-v8@4.1.3':
|
||||
resolution: {integrity: sha512-/MBdrkA8t6hbdCWFKs09dPik774xvs4Z6L4bycdCxYNLHM8oZuRyosumQMG19LUlBsB6GeVpL1q4kFFazvyKGA==}
|
||||
'@vitest/coverage-v8@4.1.4':
|
||||
resolution: {integrity: sha512-x7FptB5oDruxNPDNY2+S8tCh0pcq7ymCe1gTHcsp733jYjrJl8V1gMUlVysuCD9Kz46Xz9t1akkv08dPcYDs1w==}
|
||||
peerDependencies:
|
||||
'@vitest/browser': 4.1.3
|
||||
vitest: 4.1.3
|
||||
'@vitest/browser': 4.1.4
|
||||
vitest: 4.1.4
|
||||
peerDependenciesMeta:
|
||||
'@vitest/browser':
|
||||
optional: true
|
||||
|
||||
'@vitest/pretty-format@4.1.3':
|
||||
resolution: {integrity: sha512-hYqqwuMbpkkBodpRh4k4cQSOELxXky1NfMmQvOfKvV8zQHz8x8Dla+2wzElkMkBvSAJX5TRGHJAQvK0TcOafwg==}
|
||||
'@vitest/pretty-format@4.1.4':
|
||||
resolution: {integrity: sha512-ddmDHU0gjEUyEVLxtZa7xamrpIefdEETu3nZjWtHeZX4QxqJ7tRxSteHVXJOcr8jhiLoGAhkK4WJ3WqBpjx42A==}
|
||||
|
||||
'@vitest/utils@4.1.3':
|
||||
resolution: {integrity: sha512-Pc/Oexse/khOWsGB+w3q4yzA4te7W4gpZZAvk+fr8qXfTURZUMj5i7kuxsNK5mP/dEB6ao3jfr0rs17fHhbHdw==}
|
||||
'@vitest/utils@4.1.4':
|
||||
resolution: {integrity: sha512-13QMT+eysM5uVGa1rG4kegGYNp6cnQcsTc67ELFbhNLQO+vgsygtYJx2khvdt4gVQqSSpC/KT5FZZxUpP3Oatw==}
|
||||
|
||||
'@voidzero-dev/vite-plus-core@0.1.16':
|
||||
resolution: {integrity: sha512-fOyf14CXjcXqANFs2fCXEX+0Tn9ZjmqfFV+qTnARwIF1Kzl8WquO4XtvlDgs/fTQ91H4AyoNUgkvWdKS+C4xYA==}
|
||||
@@ -10582,33 +10582,33 @@ snapshots:
|
||||
|
||||
'@opentelemetry/semantic-conventions@1.40.0': {}
|
||||
|
||||
'@orpc/client@1.13.13(@opentelemetry/api@1.9.0)':
|
||||
'@orpc/client@1.13.14(@opentelemetry/api@1.9.0)':
|
||||
dependencies:
|
||||
'@orpc/shared': 1.13.13(@opentelemetry/api@1.9.0)
|
||||
'@orpc/standard-server': 1.13.13(@opentelemetry/api@1.9.0)
|
||||
'@orpc/standard-server-fetch': 1.13.13(@opentelemetry/api@1.9.0)
|
||||
'@orpc/standard-server-peer': 1.13.13(@opentelemetry/api@1.9.0)
|
||||
'@orpc/shared': 1.13.14(@opentelemetry/api@1.9.0)
|
||||
'@orpc/standard-server': 1.13.14(@opentelemetry/api@1.9.0)
|
||||
'@orpc/standard-server-fetch': 1.13.14(@opentelemetry/api@1.9.0)
|
||||
'@orpc/standard-server-peer': 1.13.14(@opentelemetry/api@1.9.0)
|
||||
transitivePeerDependencies:
|
||||
- '@opentelemetry/api'
|
||||
|
||||
'@orpc/contract@1.13.13(@opentelemetry/api@1.9.0)':
|
||||
'@orpc/contract@1.13.14(@opentelemetry/api@1.9.0)':
|
||||
dependencies:
|
||||
'@orpc/client': 1.13.13(@opentelemetry/api@1.9.0)
|
||||
'@orpc/shared': 1.13.13(@opentelemetry/api@1.9.0)
|
||||
'@orpc/client': 1.13.14(@opentelemetry/api@1.9.0)
|
||||
'@orpc/shared': 1.13.14(@opentelemetry/api@1.9.0)
|
||||
'@standard-schema/spec': 1.1.0
|
||||
openapi-types: 12.1.3
|
||||
transitivePeerDependencies:
|
||||
- '@opentelemetry/api'
|
||||
|
||||
'@orpc/interop@1.13.13': {}
|
||||
'@orpc/interop@1.13.14': {}
|
||||
|
||||
'@orpc/json-schema@1.13.13(@opentelemetry/api@1.9.0)(crossws@0.4.4(srvx@0.11.15))(ws@8.20.0)':
|
||||
'@orpc/json-schema@1.13.14(@opentelemetry/api@1.9.0)(crossws@0.4.4(srvx@0.11.15))(ws@8.20.0)':
|
||||
dependencies:
|
||||
'@orpc/contract': 1.13.13(@opentelemetry/api@1.9.0)
|
||||
'@orpc/interop': 1.13.13
|
||||
'@orpc/openapi': 1.13.13(@opentelemetry/api@1.9.0)(crossws@0.4.4(srvx@0.11.15))(ws@8.20.0)
|
||||
'@orpc/server': 1.13.13(@opentelemetry/api@1.9.0)(crossws@0.4.4(srvx@0.11.15))(ws@8.20.0)
|
||||
'@orpc/shared': 1.13.13(@opentelemetry/api@1.9.0)
|
||||
'@orpc/contract': 1.13.14(@opentelemetry/api@1.9.0)
|
||||
'@orpc/interop': 1.13.14
|
||||
'@orpc/openapi': 1.13.14(@opentelemetry/api@1.9.0)(crossws@0.4.4(srvx@0.11.15))(ws@8.20.0)
|
||||
'@orpc/server': 1.13.14(@opentelemetry/api@1.9.0)(crossws@0.4.4(srvx@0.11.15))(ws@8.20.0)
|
||||
'@orpc/shared': 1.13.14(@opentelemetry/api@1.9.0)
|
||||
json-schema-typed: 8.0.2
|
||||
transitivePeerDependencies:
|
||||
- '@opentelemetry/api'
|
||||
@@ -10616,24 +10616,24 @@ snapshots:
|
||||
- fastify
|
||||
- ws
|
||||
|
||||
'@orpc/openapi-client@1.13.13(@opentelemetry/api@1.9.0)':
|
||||
'@orpc/openapi-client@1.13.14(@opentelemetry/api@1.9.0)':
|
||||
dependencies:
|
||||
'@orpc/client': 1.13.13(@opentelemetry/api@1.9.0)
|
||||
'@orpc/contract': 1.13.13(@opentelemetry/api@1.9.0)
|
||||
'@orpc/shared': 1.13.13(@opentelemetry/api@1.9.0)
|
||||
'@orpc/standard-server': 1.13.13(@opentelemetry/api@1.9.0)
|
||||
'@orpc/client': 1.13.14(@opentelemetry/api@1.9.0)
|
||||
'@orpc/contract': 1.13.14(@opentelemetry/api@1.9.0)
|
||||
'@orpc/shared': 1.13.14(@opentelemetry/api@1.9.0)
|
||||
'@orpc/standard-server': 1.13.14(@opentelemetry/api@1.9.0)
|
||||
transitivePeerDependencies:
|
||||
- '@opentelemetry/api'
|
||||
|
||||
'@orpc/openapi@1.13.13(@opentelemetry/api@1.9.0)(crossws@0.4.4(srvx@0.11.15))(ws@8.20.0)':
|
||||
'@orpc/openapi@1.13.14(@opentelemetry/api@1.9.0)(crossws@0.4.4(srvx@0.11.15))(ws@8.20.0)':
|
||||
dependencies:
|
||||
'@orpc/client': 1.13.13(@opentelemetry/api@1.9.0)
|
||||
'@orpc/contract': 1.13.13(@opentelemetry/api@1.9.0)
|
||||
'@orpc/interop': 1.13.13
|
||||
'@orpc/openapi-client': 1.13.13(@opentelemetry/api@1.9.0)
|
||||
'@orpc/server': 1.13.13(@opentelemetry/api@1.9.0)(crossws@0.4.4(srvx@0.11.15))(ws@8.20.0)
|
||||
'@orpc/shared': 1.13.13(@opentelemetry/api@1.9.0)
|
||||
'@orpc/standard-server': 1.13.13(@opentelemetry/api@1.9.0)
|
||||
'@orpc/client': 1.13.14(@opentelemetry/api@1.9.0)
|
||||
'@orpc/contract': 1.13.14(@opentelemetry/api@1.9.0)
|
||||
'@orpc/interop': 1.13.14
|
||||
'@orpc/openapi-client': 1.13.14(@opentelemetry/api@1.9.0)
|
||||
'@orpc/server': 1.13.14(@opentelemetry/api@1.9.0)(crossws@0.4.4(srvx@0.11.15))(ws@8.20.0)
|
||||
'@orpc/shared': 1.13.14(@opentelemetry/api@1.9.0)
|
||||
'@orpc/standard-server': 1.13.14(@opentelemetry/api@1.9.0)
|
||||
json-schema-typed: 8.0.2
|
||||
rou3: 0.7.12
|
||||
transitivePeerDependencies:
|
||||
@@ -10642,18 +10642,18 @@ snapshots:
|
||||
- fastify
|
||||
- ws
|
||||
|
||||
'@orpc/server@1.13.13(@opentelemetry/api@1.9.0)(crossws@0.4.4(srvx@0.11.15))(ws@8.20.0)':
|
||||
'@orpc/server@1.13.14(@opentelemetry/api@1.9.0)(crossws@0.4.4(srvx@0.11.15))(ws@8.20.0)':
|
||||
dependencies:
|
||||
'@orpc/client': 1.13.13(@opentelemetry/api@1.9.0)
|
||||
'@orpc/contract': 1.13.13(@opentelemetry/api@1.9.0)
|
||||
'@orpc/interop': 1.13.13
|
||||
'@orpc/shared': 1.13.13(@opentelemetry/api@1.9.0)
|
||||
'@orpc/standard-server': 1.13.13(@opentelemetry/api@1.9.0)
|
||||
'@orpc/standard-server-aws-lambda': 1.13.13(@opentelemetry/api@1.9.0)
|
||||
'@orpc/standard-server-fastify': 1.13.13(@opentelemetry/api@1.9.0)
|
||||
'@orpc/standard-server-fetch': 1.13.13(@opentelemetry/api@1.9.0)
|
||||
'@orpc/standard-server-node': 1.13.13(@opentelemetry/api@1.9.0)
|
||||
'@orpc/standard-server-peer': 1.13.13(@opentelemetry/api@1.9.0)
|
||||
'@orpc/client': 1.13.14(@opentelemetry/api@1.9.0)
|
||||
'@orpc/contract': 1.13.14(@opentelemetry/api@1.9.0)
|
||||
'@orpc/interop': 1.13.14
|
||||
'@orpc/shared': 1.13.14(@opentelemetry/api@1.9.0)
|
||||
'@orpc/standard-server': 1.13.14(@opentelemetry/api@1.9.0)
|
||||
'@orpc/standard-server-aws-lambda': 1.13.14(@opentelemetry/api@1.9.0)
|
||||
'@orpc/standard-server-fastify': 1.13.14(@opentelemetry/api@1.9.0)
|
||||
'@orpc/standard-server-fetch': 1.13.14(@opentelemetry/api@1.9.0)
|
||||
'@orpc/standard-server-node': 1.13.14(@opentelemetry/api@1.9.0)
|
||||
'@orpc/standard-server-peer': 1.13.14(@opentelemetry/api@1.9.0)
|
||||
cookie: 1.1.1
|
||||
optionalDependencies:
|
||||
crossws: 0.4.4(srvx@0.11.15)
|
||||
@@ -10662,73 +10662,73 @@ snapshots:
|
||||
- '@opentelemetry/api'
|
||||
- fastify
|
||||
|
||||
'@orpc/shared@1.13.13(@opentelemetry/api@1.9.0)':
|
||||
'@orpc/shared@1.13.14(@opentelemetry/api@1.9.0)':
|
||||
dependencies:
|
||||
radash: 12.1.1
|
||||
type-fest: 5.5.0
|
||||
optionalDependencies:
|
||||
'@opentelemetry/api': 1.9.0
|
||||
|
||||
'@orpc/standard-server-aws-lambda@1.13.13(@opentelemetry/api@1.9.0)':
|
||||
'@orpc/standard-server-aws-lambda@1.13.14(@opentelemetry/api@1.9.0)':
|
||||
dependencies:
|
||||
'@orpc/shared': 1.13.13(@opentelemetry/api@1.9.0)
|
||||
'@orpc/standard-server': 1.13.13(@opentelemetry/api@1.9.0)
|
||||
'@orpc/standard-server-fetch': 1.13.13(@opentelemetry/api@1.9.0)
|
||||
'@orpc/standard-server-node': 1.13.13(@opentelemetry/api@1.9.0)
|
||||
'@orpc/shared': 1.13.14(@opentelemetry/api@1.9.0)
|
||||
'@orpc/standard-server': 1.13.14(@opentelemetry/api@1.9.0)
|
||||
'@orpc/standard-server-fetch': 1.13.14(@opentelemetry/api@1.9.0)
|
||||
'@orpc/standard-server-node': 1.13.14(@opentelemetry/api@1.9.0)
|
||||
transitivePeerDependencies:
|
||||
- '@opentelemetry/api'
|
||||
|
||||
'@orpc/standard-server-fastify@1.13.13(@opentelemetry/api@1.9.0)':
|
||||
'@orpc/standard-server-fastify@1.13.14(@opentelemetry/api@1.9.0)':
|
||||
dependencies:
|
||||
'@orpc/shared': 1.13.13(@opentelemetry/api@1.9.0)
|
||||
'@orpc/standard-server': 1.13.13(@opentelemetry/api@1.9.0)
|
||||
'@orpc/standard-server-node': 1.13.13(@opentelemetry/api@1.9.0)
|
||||
'@orpc/shared': 1.13.14(@opentelemetry/api@1.9.0)
|
||||
'@orpc/standard-server': 1.13.14(@opentelemetry/api@1.9.0)
|
||||
'@orpc/standard-server-node': 1.13.14(@opentelemetry/api@1.9.0)
|
||||
transitivePeerDependencies:
|
||||
- '@opentelemetry/api'
|
||||
|
||||
'@orpc/standard-server-fetch@1.13.13(@opentelemetry/api@1.9.0)':
|
||||
'@orpc/standard-server-fetch@1.13.14(@opentelemetry/api@1.9.0)':
|
||||
dependencies:
|
||||
'@orpc/shared': 1.13.13(@opentelemetry/api@1.9.0)
|
||||
'@orpc/standard-server': 1.13.13(@opentelemetry/api@1.9.0)
|
||||
'@orpc/shared': 1.13.14(@opentelemetry/api@1.9.0)
|
||||
'@orpc/standard-server': 1.13.14(@opentelemetry/api@1.9.0)
|
||||
transitivePeerDependencies:
|
||||
- '@opentelemetry/api'
|
||||
|
||||
'@orpc/standard-server-node@1.13.13(@opentelemetry/api@1.9.0)':
|
||||
'@orpc/standard-server-node@1.13.14(@opentelemetry/api@1.9.0)':
|
||||
dependencies:
|
||||
'@orpc/shared': 1.13.13(@opentelemetry/api@1.9.0)
|
||||
'@orpc/standard-server': 1.13.13(@opentelemetry/api@1.9.0)
|
||||
'@orpc/standard-server-fetch': 1.13.13(@opentelemetry/api@1.9.0)
|
||||
'@orpc/shared': 1.13.14(@opentelemetry/api@1.9.0)
|
||||
'@orpc/standard-server': 1.13.14(@opentelemetry/api@1.9.0)
|
||||
'@orpc/standard-server-fetch': 1.13.14(@opentelemetry/api@1.9.0)
|
||||
transitivePeerDependencies:
|
||||
- '@opentelemetry/api'
|
||||
|
||||
'@orpc/standard-server-peer@1.13.13(@opentelemetry/api@1.9.0)':
|
||||
'@orpc/standard-server-peer@1.13.14(@opentelemetry/api@1.9.0)':
|
||||
dependencies:
|
||||
'@orpc/shared': 1.13.13(@opentelemetry/api@1.9.0)
|
||||
'@orpc/standard-server': 1.13.13(@opentelemetry/api@1.9.0)
|
||||
'@orpc/shared': 1.13.14(@opentelemetry/api@1.9.0)
|
||||
'@orpc/standard-server': 1.13.14(@opentelemetry/api@1.9.0)
|
||||
transitivePeerDependencies:
|
||||
- '@opentelemetry/api'
|
||||
|
||||
'@orpc/standard-server@1.13.13(@opentelemetry/api@1.9.0)':
|
||||
'@orpc/standard-server@1.13.14(@opentelemetry/api@1.9.0)':
|
||||
dependencies:
|
||||
'@orpc/shared': 1.13.13(@opentelemetry/api@1.9.0)
|
||||
'@orpc/shared': 1.13.14(@opentelemetry/api@1.9.0)
|
||||
transitivePeerDependencies:
|
||||
- '@opentelemetry/api'
|
||||
|
||||
'@orpc/tanstack-query@1.13.13(@opentelemetry/api@1.9.0)(@orpc/client@1.13.13(@opentelemetry/api@1.9.0))(@tanstack/query-core@5.96.2)':
|
||||
'@orpc/tanstack-query@1.13.14(@opentelemetry/api@1.9.0)(@orpc/client@1.13.14(@opentelemetry/api@1.9.0))(@tanstack/query-core@5.97.0)':
|
||||
dependencies:
|
||||
'@orpc/client': 1.13.13(@opentelemetry/api@1.9.0)
|
||||
'@orpc/shared': 1.13.13(@opentelemetry/api@1.9.0)
|
||||
'@tanstack/query-core': 5.96.2
|
||||
'@orpc/client': 1.13.14(@opentelemetry/api@1.9.0)
|
||||
'@orpc/shared': 1.13.14(@opentelemetry/api@1.9.0)
|
||||
'@tanstack/query-core': 5.97.0
|
||||
transitivePeerDependencies:
|
||||
- '@opentelemetry/api'
|
||||
|
||||
'@orpc/zod@1.13.13(@opentelemetry/api@1.9.0)(@orpc/contract@1.13.13(@opentelemetry/api@1.9.0))(@orpc/server@1.13.13(@opentelemetry/api@1.9.0)(crossws@0.4.4(srvx@0.11.15))(ws@8.20.0))(crossws@0.4.4(srvx@0.11.15))(ws@8.20.0)(zod@4.3.6)':
|
||||
'@orpc/zod@1.13.14(@opentelemetry/api@1.9.0)(@orpc/contract@1.13.14(@opentelemetry/api@1.9.0))(@orpc/server@1.13.14(@opentelemetry/api@1.9.0)(crossws@0.4.4(srvx@0.11.15))(ws@8.20.0))(crossws@0.4.4(srvx@0.11.15))(ws@8.20.0)(zod@4.3.6)':
|
||||
dependencies:
|
||||
'@orpc/contract': 1.13.13(@opentelemetry/api@1.9.0)
|
||||
'@orpc/json-schema': 1.13.13(@opentelemetry/api@1.9.0)(crossws@0.4.4(srvx@0.11.15))(ws@8.20.0)
|
||||
'@orpc/openapi': 1.13.13(@opentelemetry/api@1.9.0)(crossws@0.4.4(srvx@0.11.15))(ws@8.20.0)
|
||||
'@orpc/server': 1.13.13(@opentelemetry/api@1.9.0)(crossws@0.4.4(srvx@0.11.15))(ws@8.20.0)
|
||||
'@orpc/shared': 1.13.13(@opentelemetry/api@1.9.0)
|
||||
'@orpc/contract': 1.13.14(@opentelemetry/api@1.9.0)
|
||||
'@orpc/json-schema': 1.13.14(@opentelemetry/api@1.9.0)(crossws@0.4.4(srvx@0.11.15))(ws@8.20.0)
|
||||
'@orpc/openapi': 1.13.14(@opentelemetry/api@1.9.0)(crossws@0.4.4(srvx@0.11.15))(ws@8.20.0)
|
||||
'@orpc/server': 1.13.14(@opentelemetry/api@1.9.0)(crossws@0.4.4(srvx@0.11.15))(ws@8.20.0)
|
||||
'@orpc/shared': 1.13.14(@opentelemetry/api@1.9.0)
|
||||
escape-string-regexp: 5.0.0
|
||||
wildcard-match: 5.1.4
|
||||
zod: 4.3.6
|
||||
@@ -11828,19 +11828,19 @@ snapshots:
|
||||
|
||||
'@tanstack/history@1.161.6': {}
|
||||
|
||||
'@tanstack/query-core@5.96.2': {}
|
||||
'@tanstack/query-core@5.97.0': {}
|
||||
|
||||
'@tanstack/react-query@5.96.2(react@19.2.5)':
|
||||
'@tanstack/react-query@5.97.0(react@19.2.5)':
|
||||
dependencies:
|
||||
'@tanstack/query-core': 5.96.2
|
||||
'@tanstack/query-core': 5.97.0
|
||||
react: 19.2.5
|
||||
|
||||
'@tanstack/react-router-ssr-query@1.166.10(@tanstack/query-core@5.96.2)(@tanstack/react-query@5.96.2(react@19.2.5))(@tanstack/react-router@1.168.10(react-dom@19.2.5(react@19.2.5))(react@19.2.5))(@tanstack/router-core@1.168.9)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)':
|
||||
'@tanstack/react-router-ssr-query@1.166.10(@tanstack/query-core@5.97.0)(@tanstack/react-query@5.97.0(react@19.2.5))(@tanstack/react-router@1.168.10(react-dom@19.2.5(react@19.2.5))(react@19.2.5))(@tanstack/router-core@1.168.9)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)':
|
||||
dependencies:
|
||||
'@tanstack/query-core': 5.96.2
|
||||
'@tanstack/react-query': 5.96.2(react@19.2.5)
|
||||
'@tanstack/query-core': 5.97.0
|
||||
'@tanstack/react-query': 5.97.0(react@19.2.5)
|
||||
'@tanstack/react-router': 1.168.10(react-dom@19.2.5(react@19.2.5))(react@19.2.5)
|
||||
'@tanstack/router-ssr-query-core': 1.167.0(@tanstack/query-core@5.96.2)(@tanstack/router-core@1.168.9)
|
||||
'@tanstack/router-ssr-query-core': 1.167.0(@tanstack/query-core@5.97.0)(@tanstack/router-core@1.168.9)
|
||||
react: 19.2.5
|
||||
react-dom: 19.2.5(react@19.2.5)
|
||||
transitivePeerDependencies:
|
||||
@@ -11943,9 +11943,9 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@tanstack/router-ssr-query-core@1.167.0(@tanstack/query-core@5.96.2)(@tanstack/router-core@1.168.9)':
|
||||
'@tanstack/router-ssr-query-core@1.167.0(@tanstack/query-core@5.97.0)(@tanstack/router-core@1.168.9)':
|
||||
dependencies:
|
||||
'@tanstack/query-core': 5.96.2
|
||||
'@tanstack/query-core': 5.97.0
|
||||
'@tanstack/router-core': 1.168.9
|
||||
|
||||
'@tanstack/router-utils@1.161.6':
|
||||
@@ -12388,36 +12388,36 @@ snapshots:
|
||||
'@types/node': 25.5.2
|
||||
optional: true
|
||||
|
||||
'@typescript/native-preview-darwin-arm64@7.0.0-dev.20260408.1':
|
||||
'@typescript/native-preview-darwin-arm64@7.0.0-dev.20260409.1':
|
||||
optional: true
|
||||
|
||||
'@typescript/native-preview-darwin-x64@7.0.0-dev.20260408.1':
|
||||
'@typescript/native-preview-darwin-x64@7.0.0-dev.20260409.1':
|
||||
optional: true
|
||||
|
||||
'@typescript/native-preview-linux-arm64@7.0.0-dev.20260408.1':
|
||||
'@typescript/native-preview-linux-arm64@7.0.0-dev.20260409.1':
|
||||
optional: true
|
||||
|
||||
'@typescript/native-preview-linux-arm@7.0.0-dev.20260408.1':
|
||||
'@typescript/native-preview-linux-arm@7.0.0-dev.20260409.1':
|
||||
optional: true
|
||||
|
||||
'@typescript/native-preview-linux-x64@7.0.0-dev.20260408.1':
|
||||
'@typescript/native-preview-linux-x64@7.0.0-dev.20260409.1':
|
||||
optional: true
|
||||
|
||||
'@typescript/native-preview-win32-arm64@7.0.0-dev.20260408.1':
|
||||
'@typescript/native-preview-win32-arm64@7.0.0-dev.20260409.1':
|
||||
optional: true
|
||||
|
||||
'@typescript/native-preview-win32-x64@7.0.0-dev.20260408.1':
|
||||
'@typescript/native-preview-win32-x64@7.0.0-dev.20260409.1':
|
||||
optional: true
|
||||
|
||||
'@typescript/native-preview@7.0.0-dev.20260408.1':
|
||||
'@typescript/native-preview@7.0.0-dev.20260409.1':
|
||||
optionalDependencies:
|
||||
'@typescript/native-preview-darwin-arm64': 7.0.0-dev.20260408.1
|
||||
'@typescript/native-preview-darwin-x64': 7.0.0-dev.20260408.1
|
||||
'@typescript/native-preview-linux-arm': 7.0.0-dev.20260408.1
|
||||
'@typescript/native-preview-linux-arm64': 7.0.0-dev.20260408.1
|
||||
'@typescript/native-preview-linux-x64': 7.0.0-dev.20260408.1
|
||||
'@typescript/native-preview-win32-arm64': 7.0.0-dev.20260408.1
|
||||
'@typescript/native-preview-win32-x64': 7.0.0-dev.20260408.1
|
||||
'@typescript/native-preview-darwin-arm64': 7.0.0-dev.20260409.1
|
||||
'@typescript/native-preview-darwin-x64': 7.0.0-dev.20260409.1
|
||||
'@typescript/native-preview-linux-arm': 7.0.0-dev.20260409.1
|
||||
'@typescript/native-preview-linux-arm64': 7.0.0-dev.20260409.1
|
||||
'@typescript/native-preview-linux-x64': 7.0.0-dev.20260409.1
|
||||
'@typescript/native-preview-win32-arm64': 7.0.0-dev.20260409.1
|
||||
'@typescript/native-preview-win32-x64': 7.0.0-dev.20260409.1
|
||||
|
||||
'@typespec/ts-http-runtime@0.3.5':
|
||||
dependencies:
|
||||
@@ -12480,10 +12480,10 @@ snapshots:
|
||||
optionalDependencies:
|
||||
'@rolldown/plugin-babel': 0.2.2(@babel/core@7.29.0)(@babel/runtime@7.29.2)(@voidzero-dev/vite-plus-core@0.1.16(@types/node@25.5.2)(jiti@2.6.1)(terser@5.46.1)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.3))(rolldown@1.0.0-rc.15)
|
||||
|
||||
'@vitest/coverage-v8@4.1.3(@voidzero-dev/vite-plus-test@0.1.16(@opentelemetry/api@1.9.0)(@types/node@25.5.2)(@voidzero-dev/vite-plus-core@0.1.16(@types/node@25.5.2)(jiti@2.6.1)(terser@5.46.1)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.3))(happy-dom@20.8.9)(jiti@2.6.1)(jsdom@29.0.1(@noble/hashes@2.0.1))(terser@5.46.1)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.3))':
|
||||
'@vitest/coverage-v8@4.1.4(@voidzero-dev/vite-plus-test@0.1.16(@opentelemetry/api@1.9.0)(@types/node@25.5.2)(@voidzero-dev/vite-plus-core@0.1.16(@types/node@25.5.2)(jiti@2.6.1)(terser@5.46.1)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.3))(happy-dom@20.8.9)(jiti@2.6.1)(jsdom@29.0.1(@noble/hashes@2.0.1))(terser@5.46.1)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.3))':
|
||||
dependencies:
|
||||
'@bcoe/v8-coverage': 1.0.2
|
||||
'@vitest/utils': 4.1.3
|
||||
'@vitest/utils': 4.1.4
|
||||
ast-v8-to-istanbul: 1.0.0
|
||||
istanbul-lib-coverage: 3.2.2
|
||||
istanbul-lib-report: 3.0.1
|
||||
@@ -12494,13 +12494,13 @@ snapshots:
|
||||
tinyrainbow: 3.1.0
|
||||
vitest: '@voidzero-dev/vite-plus-test@0.1.16(@opentelemetry/api@1.9.0)(@types/node@25.5.2)(@voidzero-dev/vite-plus-core@0.1.16(@types/node@25.5.2)(jiti@2.6.1)(terser@5.46.1)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.3))(happy-dom@20.8.9)(jiti@2.6.1)(jsdom@29.0.1(@noble/hashes@2.0.1))(terser@5.46.1)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.3)'
|
||||
|
||||
'@vitest/pretty-format@4.1.3':
|
||||
'@vitest/pretty-format@4.1.4':
|
||||
dependencies:
|
||||
tinyrainbow: 3.1.0
|
||||
|
||||
'@vitest/utils@4.1.3':
|
||||
'@vitest/utils@4.1.4':
|
||||
dependencies:
|
||||
'@vitest/pretty-format': 4.1.3
|
||||
'@vitest/pretty-format': 4.1.4
|
||||
convert-source-map: 2.0.0
|
||||
tinyrainbow: 3.1.0
|
||||
|
||||
|
||||
@@ -59,6 +59,27 @@ async function getUserFromApiKey(apiKey: string): Promise<User | null> {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the authenticated user from the same headers oRPC uses (`x-api-key`, `Authorization: Bearer`, or session cookies).
|
||||
* For callers outside oRPC handlers (e.g. MCP tools) where `context.user` is not in scope.
|
||||
*/
|
||||
export async function resolveUserFromRequestHeaders(headers: Headers): Promise<User | null> {
|
||||
// Try API key authentication first
|
||||
const apiKey = headers.get("x-api-key");
|
||||
if (apiKey) {
|
||||
const user = await getUserFromApiKey(apiKey);
|
||||
if (user) return user;
|
||||
} else {
|
||||
// Fall back to Bearer token authentication
|
||||
const user = await getUserFromBearerToken(headers);
|
||||
if (user) return user;
|
||||
}
|
||||
|
||||
// Finally, try session authentication (cookies)
|
||||
const user = await getUserFromHeaders(headers);
|
||||
return user ?? null;
|
||||
}
|
||||
|
||||
const base = os.$context<ORPCContext>();
|
||||
|
||||
export const publicProcedure = base.use(async ({ context, next }) => {
|
||||
|
||||
@@ -61,7 +61,9 @@ export const resumeDto = {
|
||||
.pick({ name: true, slug: true, tags: true, data: true, isPublic: true })
|
||||
.partial()
|
||||
.extend({ id: z.string() }),
|
||||
output: resumeSchema.omit({ password: true, userId: true, createdAt: true, updatedAt: true }),
|
||||
output: resumeSchema
|
||||
.omit({ password: true, userId: true, createdAt: true, updatedAt: true })
|
||||
.extend({ hasPassword: z.boolean() }),
|
||||
},
|
||||
|
||||
setLocked: {
|
||||
|
||||
@@ -48,6 +48,16 @@ export function buildMcpServerCard(appVersion: string) {
|
||||
),
|
||||
annotations: TOOL_ANNOTATIONS[T.listResumes],
|
||||
},
|
||||
{
|
||||
name: T.listResumeTags,
|
||||
title: "List Resume Tags",
|
||||
description: [
|
||||
"Returns a sorted list of every distinct tag used across your resumes.",
|
||||
"Useful for choosing tag filters when calling list tools or keeping naming consistent.",
|
||||
].join("\n"),
|
||||
inputSchema: toJsonSchemaCompat(z.object({})),
|
||||
annotations: TOOL_ANNOTATIONS[T.listResumeTags],
|
||||
},
|
||||
{
|
||||
name: T.getResume,
|
||||
title: "Get Resume",
|
||||
@@ -64,6 +74,17 @@ export function buildMcpServerCard(appVersion: string) {
|
||||
inputSchema: toJsonSchemaCompat(z.object({ id: resumeId })),
|
||||
annotations: TOOL_ANNOTATIONS[T.getResume],
|
||||
},
|
||||
{
|
||||
name: T.getResumeAnalysis,
|
||||
title: "Get Resume Analysis",
|
||||
description: [
|
||||
"Returns the latest saved AI analysis for a resume (scorecard, strengths, suggestions), if any.",
|
||||
"Analyses are created from the Reactive Resume web app AI flow, not from MCP.",
|
||||
`Returns JSON or a short message if none exists. Use \`${T.listResumes}\` to find resume IDs.`,
|
||||
].join("\n"),
|
||||
inputSchema: toJsonSchemaCompat(z.object({ id: resumeId })),
|
||||
annotations: TOOL_ANNOTATIONS[T.getResumeAnalysis],
|
||||
},
|
||||
{
|
||||
name: T.createResume,
|
||||
title: "Create Resume",
|
||||
@@ -92,6 +113,24 @@ export function buildMcpServerCard(appVersion: string) {
|
||||
),
|
||||
annotations: TOOL_ANNOTATIONS[T.createResume],
|
||||
},
|
||||
{
|
||||
name: T.importResume,
|
||||
title: "Import Resume",
|
||||
description: [
|
||||
"Create a new resume from a full ResumeData JSON object (e.g. an exported file from Reactive Resume).",
|
||||
"A random name and slug are assigned automatically, like the web importer.",
|
||||
`For small edits to an existing resume, prefer \`${T.patchResume}\` instead of re-importing.`,
|
||||
"Large payloads may exceed MCP client message limits — in that case, use the web UI or the HTTP API.",
|
||||
].join("\n"),
|
||||
inputSchema: toJsonSchemaCompat(
|
||||
z.object({
|
||||
data: z
|
||||
.unknown()
|
||||
.describe("Complete ResumeData JSON (same shape as get_resume output or `resume://_meta/schema`)."),
|
||||
}),
|
||||
),
|
||||
annotations: TOOL_ANNOTATIONS[T.importResume],
|
||||
},
|
||||
{
|
||||
name: T.duplicateResume,
|
||||
title: "Duplicate Resume",
|
||||
@@ -134,6 +173,38 @@ export function buildMcpServerCard(appVersion: string) {
|
||||
),
|
||||
annotations: TOOL_ANNOTATIONS[T.patchResume],
|
||||
},
|
||||
{
|
||||
name: T.updateResume,
|
||||
title: "Update Resume (metadata)",
|
||||
description: [
|
||||
"Update resume metadata only: display name, URL slug, tags, and/or public visibility.",
|
||||
"Does not change section content — use JSON Patch via the patch tool for body edits.",
|
||||
`Locked resumes cannot be updated; use \`${T.unlockResume}\` first.`,
|
||||
"Password protection cannot be set or removed via MCP; use the web app for that.",
|
||||
"",
|
||||
"Always returns your canonical share URL (`{app}/{username}/{slug}`). Anonymous viewers can use it only when `isPublic` is true; password protection from the web app still applies.",
|
||||
].join("\n"),
|
||||
inputSchema: toJsonSchemaCompat(
|
||||
z.object({
|
||||
id: resumeId,
|
||||
name: z.string().min(1).max(64).optional().describe("Display name for the resume."),
|
||||
slug: z
|
||||
.string()
|
||||
.min(1)
|
||||
.max(64)
|
||||
.optional()
|
||||
.describe("URL-friendly slug; must stay unique among your resumes."),
|
||||
tags: z.array(z.string()).optional().describe("Replace the resume's tags (omit to leave unchanged)."),
|
||||
isPublic: z
|
||||
.boolean()
|
||||
.optional()
|
||||
.describe(
|
||||
"When true, anyone with the link can view the public resume (subject to password if set in the app).",
|
||||
),
|
||||
}),
|
||||
),
|
||||
annotations: TOOL_ANNOTATIONS[T.updateResume],
|
||||
},
|
||||
{
|
||||
name: T.deleteResume,
|
||||
title: "Delete Resume",
|
||||
@@ -152,7 +223,7 @@ export function buildMcpServerCard(appVersion: string) {
|
||||
description: [
|
||||
"Lock a resume to prevent any modifications.",
|
||||
"",
|
||||
`When locked, a resume cannot be edited (${T.patchResume}), updated, or deleted.`,
|
||||
`When locked, a resume cannot be edited (${T.patchResume}, ${T.updateResume}), or deleted.`,
|
||||
`Use \`${T.unlockResume}\` to re-enable editing.`,
|
||||
].join("\n"),
|
||||
inputSchema: toJsonSchemaCompat(z.object({ id: resumeId })),
|
||||
|
||||
@@ -1,14 +1,20 @@
|
||||
/** Hierarchical MCP tool names (SEP-986-style namespacing). */
|
||||
/**
|
||||
* Prefixed MCP tool names for multi-server clients.
|
||||
*/
|
||||
export const MCP_TOOL_NAME = {
|
||||
listResumes: "reactive_resume.list_resumes",
|
||||
getResume: "reactive_resume.get_resume",
|
||||
createResume: "reactive_resume.create_resume",
|
||||
duplicateResume: "reactive_resume.duplicate_resume",
|
||||
patchResume: "reactive_resume.patch_resume",
|
||||
deleteResume: "reactive_resume.delete_resume",
|
||||
lockResume: "reactive_resume.lock_resume",
|
||||
unlockResume: "reactive_resume.unlock_resume",
|
||||
exportResumePdf: "reactive_resume.export_resume_pdf",
|
||||
getResumeScreenshot: "reactive_resume.get_resume_screenshot",
|
||||
getResumeStatistics: "reactive_resume.get_resume_statistics",
|
||||
listResumes: "reactive_resume_list_resumes",
|
||||
listResumeTags: "reactive_resume_list_resume_tags",
|
||||
getResume: "reactive_resume_get_resume",
|
||||
getResumeAnalysis: "reactive_resume_get_resume_analysis",
|
||||
createResume: "reactive_resume_create_resume",
|
||||
importResume: "reactive_resume_import_resume",
|
||||
duplicateResume: "reactive_resume_duplicate_resume",
|
||||
patchResume: "reactive_resume_patch_resume",
|
||||
updateResume: "reactive_resume_update_resume",
|
||||
deleteResume: "reactive_resume_delete_resume",
|
||||
lockResume: "reactive_resume_lock_resume",
|
||||
unlockResume: "reactive_resume_unlock_resume",
|
||||
exportResumePdf: "reactive_resume_export_resume_pdf",
|
||||
getResumeScreenshot: "reactive_resume_get_resume_screenshot",
|
||||
getResumeStatistics: "reactive_resume_get_resume_statistics",
|
||||
} as const;
|
||||
|
||||
@@ -12,18 +12,36 @@ export const TOOL_ANNOTATIONS: Record<McpRegisteredToolName, ToolAnnotations> =
|
||||
idempotentHint: true,
|
||||
openWorldHint: false,
|
||||
},
|
||||
[MCP_TOOL_NAME.listResumeTags]: {
|
||||
readOnlyHint: true,
|
||||
destructiveHint: false,
|
||||
idempotentHint: true,
|
||||
openWorldHint: false,
|
||||
},
|
||||
[MCP_TOOL_NAME.getResume]: {
|
||||
readOnlyHint: true,
|
||||
destructiveHint: false,
|
||||
idempotentHint: true,
|
||||
openWorldHint: false,
|
||||
},
|
||||
[MCP_TOOL_NAME.getResumeAnalysis]: {
|
||||
readOnlyHint: true,
|
||||
destructiveHint: false,
|
||||
idempotentHint: true,
|
||||
openWorldHint: false,
|
||||
},
|
||||
[MCP_TOOL_NAME.createResume]: {
|
||||
readOnlyHint: false,
|
||||
destructiveHint: false,
|
||||
idempotentHint: false,
|
||||
openWorldHint: false,
|
||||
},
|
||||
[MCP_TOOL_NAME.importResume]: {
|
||||
readOnlyHint: false,
|
||||
destructiveHint: false,
|
||||
idempotentHint: false,
|
||||
openWorldHint: false,
|
||||
},
|
||||
[MCP_TOOL_NAME.duplicateResume]: {
|
||||
readOnlyHint: false,
|
||||
destructiveHint: false,
|
||||
@@ -36,6 +54,12 @@ export const TOOL_ANNOTATIONS: Record<McpRegisteredToolName, ToolAnnotations> =
|
||||
idempotentHint: false,
|
||||
openWorldHint: false,
|
||||
},
|
||||
[MCP_TOOL_NAME.updateResume]: {
|
||||
readOnlyHint: false,
|
||||
destructiveHint: false,
|
||||
idempotentHint: false,
|
||||
openWorldHint: false,
|
||||
},
|
||||
[MCP_TOOL_NAME.deleteResume]: {
|
||||
readOnlyHint: false,
|
||||
destructiveHint: true,
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
||||
import type { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
|
||||
|
||||
import { getRequestHeaders } from "@tanstack/react-start/server";
|
||||
import z from "zod";
|
||||
|
||||
import { client } from "@/integrations/orpc/client";
|
||||
import { resolveUserFromRequestHeaders } from "@/integrations/orpc/context";
|
||||
import { resumeDataSchema } from "@/schema/resume/data";
|
||||
import { env } from "@/utils/env";
|
||||
import { jsonPatchOperationSchema } from "@/utils/resume/patch";
|
||||
|
||||
import { MCP_TOOL_NAME } from "./mcp-tool-names";
|
||||
@@ -55,6 +59,25 @@ function text(value: string): CallToolResult {
|
||||
return { content: [{ type: "text", text: value }] };
|
||||
}
|
||||
|
||||
function buildResumeShareUrl(username: string, slug: string): string {
|
||||
const base = env.APP_URL.replace(/\/$/, "");
|
||||
return `${base}/${encodeURIComponent(username)}/${encodeURIComponent(slug)}`;
|
||||
}
|
||||
|
||||
function resumeShareUrlNotes(input: { isPublic: boolean; hasPassword: boolean }): string {
|
||||
const lines = [
|
||||
"Anyone can open this link without signing in only when the resume is public (`isPublic: true`).",
|
||||
input.isPublic
|
||||
? "This resume is currently public."
|
||||
: "This resume is currently private; the URL is still your canonical share link if you make it public later.",
|
||||
];
|
||||
if (input.hasPassword)
|
||||
lines.push(
|
||||
"Password protection is enabled in the web app; visitors may need that password before content is shown.",
|
||||
);
|
||||
return lines.join("\n");
|
||||
}
|
||||
|
||||
// ── Shared Zod Fragments ────────────────────────────────────────
|
||||
|
||||
const T = MCP_TOOL_NAME;
|
||||
@@ -107,6 +130,27 @@ export function registerTools(server: McpServer) {
|
||||
),
|
||||
);
|
||||
|
||||
// ── List Resume Tags ──────────────────────────────────────────
|
||||
server.registerTool(
|
||||
T.listResumeTags,
|
||||
{
|
||||
title: "List Resume Tags",
|
||||
description: [
|
||||
"Returns a sorted list of every distinct tag used across your resumes.",
|
||||
"Useful for choosing tag filters when calling list tools or keeping naming consistent.",
|
||||
].join("\n"),
|
||||
inputSchema: z.object({}),
|
||||
annotations: TOOL_ANNOTATIONS[T.listResumeTags],
|
||||
},
|
||||
withErrorHandling("listing resume tags", async () => {
|
||||
const tags = await client.resume.tags.list();
|
||||
|
||||
if (tags.length === 0) return text("No tags in use yet. Add tags when creating or updating a resume.");
|
||||
|
||||
return text(JSON.stringify(tags, null, 2));
|
||||
}),
|
||||
);
|
||||
|
||||
// ── Get Resume ────────────────────────────────────────────────
|
||||
server.registerTool(
|
||||
T.getResume,
|
||||
@@ -132,6 +176,28 @@ export function registerTools(server: McpServer) {
|
||||
}),
|
||||
);
|
||||
|
||||
// ── Get Resume Analysis ───────────────────────────────────────
|
||||
server.registerTool(
|
||||
T.getResumeAnalysis,
|
||||
{
|
||||
title: "Get Resume Analysis",
|
||||
description: [
|
||||
"Returns the latest saved AI analysis for a resume (scorecard, strengths, suggestions), if any.",
|
||||
"Analyses are created from the Reactive Resume web app AI flow, not from MCP.",
|
||||
`Returns JSON or a short message if none exists. Use \`${T.listResumes}\` to find resume IDs.`,
|
||||
].join("\n"),
|
||||
inputSchema: z.object({ id: resumeIdSchema }),
|
||||
annotations: TOOL_ANNOTATIONS[T.getResumeAnalysis],
|
||||
},
|
||||
withErrorHandling("getting resume analysis", async ({ id }: { id: string }) => {
|
||||
const analysis = await client.resume.analysis.getById({ id });
|
||||
|
||||
if (!analysis) return text("No saved analysis for this resume yet.");
|
||||
|
||||
return text(JSON.stringify(analysis, null, 2));
|
||||
}),
|
||||
);
|
||||
|
||||
// ── Create Resume ─────────────────────────────────────────────
|
||||
server.registerTool(
|
||||
T.createResume,
|
||||
@@ -182,6 +248,47 @@ export function registerTools(server: McpServer) {
|
||||
),
|
||||
);
|
||||
|
||||
// ── Import Resume ─────────────────────────────────────────────
|
||||
server.registerTool(
|
||||
T.importResume,
|
||||
{
|
||||
title: "Import Resume",
|
||||
description: [
|
||||
"Create a new resume from a full ResumeData JSON object (e.g. an exported file from Reactive Resume).",
|
||||
"A random name and slug are assigned automatically, like the web importer.",
|
||||
`For small edits to an existing resume, prefer \`${T.patchResume}\` instead of re-importing.`,
|
||||
"Large payloads may exceed MCP client message limits — in that case, use the web UI or the HTTP API.",
|
||||
].join("\n"),
|
||||
inputSchema: z.object({
|
||||
data: z
|
||||
.unknown()
|
||||
.describe(
|
||||
"Complete ResumeData JSON (same shape as `reactive_resume_get_resume` body or `resume://_meta/schema`).",
|
||||
),
|
||||
}),
|
||||
annotations: TOOL_ANNOTATIONS[T.importResume],
|
||||
},
|
||||
withErrorHandling("importing resume", async ({ data }: { data: unknown }) => {
|
||||
const parsed = resumeDataSchema.safeParse(data);
|
||||
if (!parsed.success)
|
||||
return {
|
||||
isError: true,
|
||||
content: [
|
||||
{
|
||||
type: "text",
|
||||
text: `Invalid ResumeData: ${parsed.error.message}\n\nHint: Ensure the JSON matches the schema at resume://_meta/schema`,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const id = await client.resume.import({ data: parsed.data });
|
||||
|
||||
return text(
|
||||
`Imported resume (ID: ${id}).\n\nNext steps: Use \`${T.getResume}\` to inspect metadata (name/slug were auto-generated), or \`${T.updateResume}\` / \`${T.patchResume}\` to adjust.`,
|
||||
);
|
||||
}),
|
||||
);
|
||||
|
||||
// ── Duplicate Resume ──────────────────────────────────────────
|
||||
server.registerTool(
|
||||
T.duplicateResume,
|
||||
@@ -259,6 +366,80 @@ export function registerTools(server: McpServer) {
|
||||
}),
|
||||
);
|
||||
|
||||
// ── Update Resume (metadata) ─────────────────────────────────
|
||||
server.registerTool(
|
||||
T.updateResume,
|
||||
{
|
||||
title: "Update Resume (metadata)",
|
||||
description: [
|
||||
"Update resume metadata only: display name, URL slug, tags, and/or public visibility.",
|
||||
"Does not change section content — use JSON Patch via the patch tool for body edits.",
|
||||
`Locked resumes cannot be updated; use \`${T.unlockResume}\` first.`,
|
||||
"Password protection cannot be set or removed via MCP; use the web app for that.",
|
||||
"",
|
||||
"Always returns your canonical share URL (`{app}/{username}/{slug}`). Anonymous viewers can use it only when `isPublic` is true; password protection from the web app still applies.",
|
||||
].join("\n"),
|
||||
inputSchema: z.object({
|
||||
id: resumeIdSchema,
|
||||
name: z.string().min(1).max(64).optional().describe("Display name for the resume."),
|
||||
slug: z.string().min(1).max(64).optional().describe("URL-friendly slug; must stay unique among your resumes."),
|
||||
tags: z.array(z.string()).optional().describe("Replace the resume's tags (omit to leave unchanged)."),
|
||||
isPublic: z
|
||||
.boolean()
|
||||
.optional()
|
||||
.describe(
|
||||
"When true, anyone with the link can view the public resume (subject to password if set in the app).",
|
||||
),
|
||||
}),
|
||||
annotations: TOOL_ANNOTATIONS[T.updateResume],
|
||||
},
|
||||
withErrorHandling(
|
||||
"updating resume",
|
||||
async (params: { id: string; name?: string; slug?: string; tags?: string[]; isPublic?: boolean }) => {
|
||||
const { id, name, slug, tags, isPublic } = params;
|
||||
if (name === undefined && slug === undefined && tags === undefined && isPublic === undefined)
|
||||
throw new Error("Provide at least one of: name, slug, tags, isPublic.");
|
||||
|
||||
const resume = await client.resume.update({
|
||||
id,
|
||||
...(name !== undefined ? { name } : {}),
|
||||
...(slug !== undefined ? { slug } : {}),
|
||||
...(tags !== undefined ? { tags } : {}),
|
||||
...(isPublic !== undefined ? { isPublic } : {}),
|
||||
});
|
||||
|
||||
const headers = getRequestHeaders();
|
||||
const user = await resolveUserFromRequestHeaders(headers);
|
||||
const username =
|
||||
user && "username" in user && typeof (user as { username: unknown }).username === "string"
|
||||
? (user as { username: string }).username
|
||||
: "";
|
||||
const shareUrl =
|
||||
username !== ""
|
||||
? buildResumeShareUrl(username, resume.slug)
|
||||
: "(could not build share URL — missing username on account)";
|
||||
|
||||
const payload = {
|
||||
id: resume.id,
|
||||
name: resume.name,
|
||||
slug: resume.slug,
|
||||
tags: resume.tags,
|
||||
isPublic: resume.isPublic,
|
||||
hasPassword: resume.hasPassword,
|
||||
shareUrl,
|
||||
};
|
||||
|
||||
return text(
|
||||
[
|
||||
JSON.stringify(payload, null, 2),
|
||||
"",
|
||||
resumeShareUrlNotes({ isPublic: resume.isPublic, hasPassword: resume.hasPassword }),
|
||||
].join("\n"),
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
// ── Delete Resume ─────────────────────────────────────────────
|
||||
server.registerTool(
|
||||
T.deleteResume,
|
||||
@@ -288,7 +469,7 @@ export function registerTools(server: McpServer) {
|
||||
description: [
|
||||
"Lock a resume to prevent any modifications.",
|
||||
"",
|
||||
`When locked, a resume cannot be edited (${T.patchResume}), updated, or deleted.`,
|
||||
`When locked, a resume cannot be edited (${T.patchResume}, ${T.updateResume}), or deleted.`,
|
||||
"Useful for protecting finalized resumes from accidental changes.",
|
||||
`Use \`${T.unlockResume}\` to re-enable editing.`,
|
||||
].join("\n"),
|
||||
|
||||
@@ -34,9 +34,12 @@ function createMcpServer() {
|
||||
instructions: [
|
||||
"You are connected to Reactive Resume over MCP.",
|
||||
"Authenticate with OAuth (recommended) or an API key (`x-api-key`).",
|
||||
"Discover resume IDs with `reactive_resume.list_resumes` (not `resources/list`).",
|
||||
"Read schema at `resume://_meta/schema`; read resume JSON via `resume://{id}` or `reactive_resume.get_resume`.",
|
||||
"Apply edits with JSON Patch through `reactive_resume.patch_resume`.",
|
||||
"Discover resume IDs with `reactive_resume_list_resumes` (not `resources/list`).",
|
||||
"List distinct tags with `reactive_resume_list_resume_tags`.",
|
||||
"Read schema at `resume://_meta/schema`; read resume JSON via `resume://{id}` or `reactive_resume_get_resume`.",
|
||||
"Apply body edits with JSON Patch through `reactive_resume_patch_resume`.",
|
||||
"Change name, slug, tags, or public visibility with `reactive_resume_update_resume` (returns canonical share URL; anonymous access only when `isPublic` is true; passwords are managed in the web app only).",
|
||||
"Import full ResumeData JSON with `reactive_resume_import_resume`; read saved AI analysis with `reactive_resume_get_resume_analysis`.",
|
||||
].join(" "),
|
||||
},
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user