gsclaw 0.0.0-stage → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +176 -2
- package/dist/adapters/netlify.js +15 -0
- package/dist/adapters/netlify.js.map +1 -0
- package/dist/adapters/node-http.js +2 -0
- package/dist/adapters/stdio.js +37 -0
- package/dist/adapters/stdio.js.map +1 -0
- package/dist/adapters/vercel.js +15 -0
- package/dist/adapters/vercel.js.map +1 -0
- package/dist/app-DhK9JWEH.js +4489 -0
- package/dist/app-DhK9JWEH.js.map +1 -0
- package/dist/cli.js +65 -0
- package/dist/cli.js.map +1 -0
- package/dist/node-http-BBSleZ3g.js +118 -0
- package/dist/node-http-BBSleZ3g.js.map +1 -0
- package/dist/public/assets/dashboard.css +1 -0
- package/dist/public/assets/dashboard.js +5 -0
- package/dist/public/assets/favicon.svg +15 -0
- package/dist/public/robots.txt +2 -0
- package/package.json +89 -4
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Anton Tuyakhov and GSClaw contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,177 @@
|
|
|
1
|
-
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="assets/logo.svg" width="88" height="88" alt="">
|
|
3
|
+
</p>
|
|
2
4
|
|
|
3
|
-
|
|
5
|
+
<h1 align="center">GSClaw</h1>
|
|
6
|
+
|
|
7
|
+
<p align="center"><strong>Sink your claws into your Search Console data.</strong></p>
|
|
8
|
+
|
|
9
|
+
<p align="center">
|
|
10
|
+
An open-source MCP server that gives Claude, ChatGPT, Cursor and other AI assistants first-party
|
|
11
|
+
access to Google Search Console. Deploy it in one click, connect it from claude.ai, and ask your
|
|
12
|
+
SEO questions in plain language.
|
|
13
|
+
</p>
|
|
14
|
+
|
|
15
|
+
<p align="center">
|
|
16
|
+
<a href="https://github.com/tuyakhov/gsclaw/actions/workflows/ci.yml"><img src="https://github.com/tuyakhov/gsclaw/actions/workflows/ci.yml/badge.svg" alt="CI"></a>
|
|
17
|
+
<a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-0d9488" alt="MIT license"></a>
|
|
18
|
+
<a href="https://modelcontextprotocol.io"><img src="https://img.shields.io/badge/MCP-remote%20%2B%20stdio-7c3aed" alt="MCP: remote and stdio"></a>
|
|
19
|
+
</p>
|
|
20
|
+
|
|
21
|
+
<p align="center">
|
|
22
|
+
<picture>
|
|
23
|
+
<source media="(prefers-color-scheme: dark)" srcset="docs/images/overview-dark.png">
|
|
24
|
+
<img src="docs/images/overview.png" width="860" alt="The GSClaw dashboard: clicks, impressions, CTR and position with a daily trend chart and top queries">
|
|
25
|
+
</picture>
|
|
26
|
+
</p>
|
|
27
|
+
|
|
28
|
+
## Ask your AI things like
|
|
29
|
+
|
|
30
|
+
- _"Which queries are stuck on page two with lots of impressions, and what should I change on each
|
|
31
|
+
page?"_
|
|
32
|
+
- _"Compare the last 28 days with the same period last year. What drove the difference?"_
|
|
33
|
+
- _"Where do two of my pages compete for the same query?"_
|
|
34
|
+
- _"Which blog posts have been losing clicks for three months straight?"_
|
|
35
|
+
- _"Is /pricing indexed? Which canonical did Google choose, and when was it last crawled?"_
|
|
36
|
+
- _"Run a full SEO health check on my site."_
|
|
37
|
+
|
|
38
|
+
## Why GSClaw
|
|
39
|
+
|
|
40
|
+
- **Works where you already chat.** A remote MCP endpoint over HTTPS for claude.ai (web, desktop
|
|
41
|
+
and mobile), ChatGPT, Claude Code, Cursor and VS Code, plus local stdio.
|
|
42
|
+
- **Answers, not raw rows.** Analysis tools find striking-distance keywords, CTR gaps,
|
|
43
|
+
cannibalization and decaying content, and compare periods, returning compact results that fit
|
|
44
|
+
in your AI's context.
|
|
45
|
+
- **Your data stays yours.** GSClaw runs on your own account and talks straight to Google's API.
|
|
46
|
+
There is no third-party service and no database; it stores nothing.
|
|
47
|
+
- **One-click deploys.** Vercel, Netlify, Cloudflare Workers, Render, Railway, DigitalOcean, or
|
|
48
|
+
any Docker host.
|
|
49
|
+
- **A dashboard included.** See the same numbers your AI sees, find opportunities, and copy
|
|
50
|
+
connection snippets.
|
|
51
|
+
- **Secure by default.** Refuses to start without authentication, signs clients in with OAuth
|
|
52
|
+
2.1, and stays read-only unless you enable writes.
|
|
53
|
+
|
|
54
|
+
## Get started
|
|
55
|
+
|
|
56
|
+
1. **Create a Google service account** and add its email to your Search Console properties
|
|
57
|
+
([setup guide](docs/setup.md), about 10 minutes).
|
|
58
|
+
2. **Deploy** with a button and paste two values: `GOOGLE_SERVICE_ACCOUNT_JSON` (the key) and
|
|
59
|
+
`GSCLAW_ACCESS_TOKEN` (a long random secret; Render and Railway generate it for you).
|
|
60
|
+
|
|
61
|
+
[](<https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Ftuyakhov%2Fgsclaw&env=GOOGLE_SERVICE_ACCOUNT_JSON,GSCLAW_ACCESS_TOKEN&envDescription=Service-account%20key%20JSON%20and%20a%20long%20random%20access%20token%20(openssl%20rand%20-hex%2032)&envLink=https%3A%2F%2Fgithub.com%2Ftuyakhov%2Fgsclaw%2Fblob%2Fmain%2Fdocs%2Fsetup.md&project-name=gsclaw&repository-name=gsclaw>)
|
|
62
|
+
[](https://app.netlify.com/start/deploy?repository=https://github.com/tuyakhov/gsclaw)
|
|
63
|
+
[](https://deploy.workers.cloudflare.com/?url=https://github.com/tuyakhov/gsclaw)
|
|
64
|
+
[](https://render.com/deploy?repo=https://github.com/tuyakhov/gsclaw)
|
|
65
|
+
[](https://railway.com/deploy/gsclaw?utm_medium=integration&utm_source=button&utm_campaign=gsclaw)
|
|
66
|
+
[](https://cloud.digitalocean.com/apps/new?repo=https://github.com/tuyakhov/gsclaw/tree/main)
|
|
67
|
+
|
|
68
|
+
Or run the Docker image anywhere:
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
docker run -p 3000:3000 \
|
|
72
|
+
-e GOOGLE_SERVICE_ACCOUNT_JSON="$(cat service-account.json)" \
|
|
73
|
+
-e GSCLAW_ACCESS_TOKEN="$(openssl rand -hex 32)" \
|
|
74
|
+
ghcr.io/tuyakhov/gsclaw
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Platform notes (free tiers, timeouts, updates): [deploy guide](docs/deploy/README.md).
|
|
78
|
+
|
|
79
|
+
3. **Connect your AI.** Open your deployment, sign in with the access token, and copy a snippet
|
|
80
|
+
from the **Connect** page. For claude.ai: Settings → Connectors → Add custom connector → paste
|
|
81
|
+
`https://<your-deployment>/mcp` → Connect, then approve with your access token.
|
|
82
|
+
|
|
83
|
+
Several people with different Search Console access? Use [Google OAuth mode](docs/oauth.md)
|
|
84
|
+
instead: everyone signs in with their own Google account and only sees their own properties.
|
|
85
|
+
|
|
86
|
+
## Connect any client
|
|
87
|
+
|
|
88
|
+
| Client | How |
|
|
89
|
+
| ---------------------------------- | --------------------------------------------------------------------------------------------------------------- |
|
|
90
|
+
| claude.ai, Claude Desktop & mobile | Settings → Connectors → Add custom connector → `https://<your-deployment>/mcp` |
|
|
91
|
+
| Claude Code | `claude mcp add --transport http gsclaw https://<your-deployment>/mcp`, then `/mcp` to sign in |
|
|
92
|
+
| Cursor | `{ "mcpServers": { "gsclaw": { "url": "https://<your-deployment>/mcp" } } }` in `~/.cursor/mcp.json` |
|
|
93
|
+
| VS Code | `{ "servers": { "gsclaw": { "type": "http", "url": "https://<your-deployment>/mcp" } } }` in `.vscode/mcp.json` |
|
|
94
|
+
| ChatGPT | Add a custom connector (developer mode) with the same URL and OAuth |
|
|
95
|
+
| Local (stdio) | `claude mcp add gsclaw -e GOOGLE_APPLICATION_CREDENTIALS=/path/to/key.json -- npx -y gsclaw` |
|
|
96
|
+
|
|
97
|
+
Each remote client opens a GSClaw sign-in page the first time: enter your access token, or sign
|
|
98
|
+
in with Google in OAuth mode. Clients that prefer headers can send
|
|
99
|
+
`Authorization: Bearer <token>` instead; the dashboard's Connect page has every variant.
|
|
100
|
+
|
|
101
|
+
## Tools
|
|
102
|
+
|
|
103
|
+
| Tool | What it does |
|
|
104
|
+
| ------------------------------------ | ------------------------------------------------------------------------------------------- |
|
|
105
|
+
| `list_sites` | Properties the server can access, with permission levels |
|
|
106
|
+
| `search_analytics` | Raw performance query: any dimensions, filters (incl. regex), search types, auto-pagination |
|
|
107
|
+
| `compare_periods` | Current vs previous period or year over year, with top gainers and losers |
|
|
108
|
+
| `striking_distance_keywords` | Queries at positions ~8–20 with meaningful impressions, plus potential clicks |
|
|
109
|
+
| `ctr_opportunities` | High-impression rows with CTR well below the expected CTR for their position |
|
|
110
|
+
| `keyword_cannibalization` | Queries where several of your pages split impressions |
|
|
111
|
+
| `content_decay` | Pages with sustained click decline across consecutive windows |
|
|
112
|
+
| `page_report` | One page: totals vs previous period, trend, top queries and index status |
|
|
113
|
+
| `inspect_url` / `batch_inspect_urls` | URL Inspection: index status, canonicals, last crawl, rich results |
|
|
114
|
+
| `list_sitemaps` / `get_sitemap` | Sitemap status, errors, warnings and submitted counts |
|
|
115
|
+
| `submit_sitemap` / `delete_sitemap` | Write tools, only when `GSCLAW_ALLOW_WRITES=true` |
|
|
116
|
+
|
|
117
|
+
Prompt: `seo_health_check` runs a full property review with these tools. Every tool returns
|
|
118
|
+
readable text plus structured data, and carries MCP annotations that tell clients which tools only
|
|
119
|
+
read.
|
|
120
|
+
|
|
121
|
+
## Dashboard
|
|
122
|
+
|
|
123
|
+
Every deployment serves a small dashboard at `/` (turn it off with `GSCLAW_DASHBOARD=false`). It
|
|
124
|
+
calls the exact same tool functions as the MCP server, so its numbers always match what your AI
|
|
125
|
+
sees, and every table exports to CSV.
|
|
126
|
+
|
|
127
|
+
<table>
|
|
128
|
+
<tr>
|
|
129
|
+
<td width="50%"><img src="docs/images/opportunities.png" alt="Opportunities: striking-distance keywords with potential clicks and Ask AI buttons"></td>
|
|
130
|
+
<td width="50%"><img src="docs/images/connect.png" alt="Connect: copy-paste snippets for claude.ai, Claude Code, Cursor and more"></td>
|
|
131
|
+
</tr>
|
|
132
|
+
<tr>
|
|
133
|
+
<td><strong>Opportunities.</strong> Striking distance, CTR gaps, cannibalization and content decay. "Ask AI" copies a ready-made prompt.</td>
|
|
134
|
+
<td><strong>Connect.</strong> Snippets for every client, with secrets hidden until you reveal them.</td>
|
|
135
|
+
</tr>
|
|
136
|
+
<tr>
|
|
137
|
+
<td><img src="docs/images/setup.png" alt="Setup and health: live Google connection check and visible properties"></td>
|
|
138
|
+
<td><img src="docs/images/overview-dark.png" alt="The Overview page in dark mode"></td>
|
|
139
|
+
</tr>
|
|
140
|
+
<tr>
|
|
141
|
+
<td><strong>Setup & health.</strong> A live Google check, which properties are visible, and what to fix.</td>
|
|
142
|
+
<td><strong>Light and dark, desktop and phone.</strong> Plus Indexing (sitemaps, URL Inspection) and Activity (recent tool calls).</td>
|
|
143
|
+
</tr>
|
|
144
|
+
</table>
|
|
145
|
+
|
|
146
|
+
## Authentication modes
|
|
147
|
+
|
|
148
|
+
GSClaw never runs open: it refuses to start until one of these is configured.
|
|
149
|
+
|
|
150
|
+
| | Service account (default) | Google OAuth |
|
|
151
|
+
| -------------------- | -------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------- |
|
|
152
|
+
| Who sees what | Everyone you give the token to sees the service account's properties | Each person sees the properties their own Google account can access |
|
|
153
|
+
| Clients sign in with | The access token (OAuth sign-in page, bearer header or secret URL) | Their Google account |
|
|
154
|
+
| Best for | You, or a team sharing the same properties | Agencies and teams where people have different access |
|
|
155
|
+
| Required variables | `GOOGLE_SERVICE_ACCOUNT_JSON`, `GSCLAW_ACCESS_TOKEN` | `GOOGLE_OAUTH_CLIENT_ID`, `GOOGLE_OAUTH_CLIENT_SECRET`, `GSCLAW_ENCRYPTION_KEY`, `PUBLIC_BASE_URL` |
|
|
156
|
+
| Guide | [Setup guide](docs/setup.md) | [Google OAuth mode](docs/oauth.md) |
|
|
157
|
+
|
|
158
|
+
Every setting is documented in [.env.example](.env.example).
|
|
159
|
+
|
|
160
|
+
## Documentation
|
|
161
|
+
|
|
162
|
+
- [Setup guide](docs/setup.md): Google Cloud, service account, first deploy
|
|
163
|
+
- [Google OAuth mode](docs/oauth.md): multi-user sign-in with Google
|
|
164
|
+
- [Deploy guide](docs/deploy/README.md): per-platform notes and updating
|
|
165
|
+
- [Troubleshooting](docs/troubleshooting.md): common errors and fixes
|
|
166
|
+
- [Architecture](docs/ARCHITECTURE.md): how it's built and why
|
|
167
|
+
- [Security](SECURITY.md): security model and how to report a vulnerability
|
|
168
|
+
|
|
169
|
+
## Contributing
|
|
170
|
+
|
|
171
|
+
Issues and pull requests are welcome. `pnpm build && pnpm demo` runs the server and dashboard on
|
|
172
|
+
synthetic data with no Google account. See [CONTRIBUTING.md](CONTRIBUTING.md).
|
|
173
|
+
|
|
174
|
+
## License
|
|
175
|
+
|
|
176
|
+
[MIT](LICENSE). GSClaw is an independent project, not affiliated with or endorsed by Google or
|
|
177
|
+
OpenClaw. Google Search Console is a trademark of Google LLC.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { t as createApp } from "../app-DhK9JWEH.js";
|
|
2
|
+
//#region src/adapters/netlify.ts
|
|
3
|
+
let app;
|
|
4
|
+
function readEnv() {
|
|
5
|
+
return globalThis.Netlify?.env?.toObject?.() ?? process.env;
|
|
6
|
+
}
|
|
7
|
+
/** Netlify Functions (v2) handler; `netlify/functions/gsclaw.mjs` re-exports it with its route config. */
|
|
8
|
+
function netlifyFetch(request) {
|
|
9
|
+
app ??= createApp(readEnv(), { name: "netlify" });
|
|
10
|
+
return app.fetch(request);
|
|
11
|
+
}
|
|
12
|
+
//#endregion
|
|
13
|
+
export { netlifyFetch };
|
|
14
|
+
|
|
15
|
+
//# sourceMappingURL=netlify.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"netlify.js","names":[],"sources":["../../src/adapters/netlify.ts"],"sourcesContent":["import { createApp, type App } from '../core/app.js';\nimport type { Env } from '../core/config.js';\n\ninterface NetlifyGlobal {\n env?: { toObject?: () => Record<string, string> };\n}\n\nlet app: App | undefined;\n\nfunction readEnv(): Env {\n const netlify = (globalThis as { Netlify?: NetlifyGlobal }).Netlify;\n return netlify?.env?.toObject?.() ?? process.env;\n}\n\n/** Netlify Functions (v2) handler; `netlify/functions/gsclaw.mjs` re-exports it with its route config. */\nexport function netlifyFetch(request: Request): Promise<Response> {\n app ??= createApp(readEnv(), { name: 'netlify' });\n return app.fetch(request);\n}\n"],"mappings":";;AAOA,IAAI;AAEJ,SAAS,UAAe;CAEtB,OADiB,WAA2C,SAC5C,KAAK,WAAW,KAAK,QAAQ;AAC/C;;AAGA,SAAgB,aAAa,SAAqC;CAChE,QAAQ,UAAU,QAAQ,GAAG,EAAE,MAAM,UAAU,CAAC;CAChD,OAAO,IAAI,MAAM,OAAO;AAC1B"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { c as stderrWriter, n as createRuntime, o as formatConfigErrors, r as buildMcpServer, s as loadConfig } from "../app-DhK9JWEH.js";
|
|
2
|
+
import { t as SetupError } from "../node-http-BBSleZ3g.js";
|
|
3
|
+
import { readFileSync } from "node:fs";
|
|
4
|
+
import { serveStdio } from "@modelcontextprotocol/server/stdio";
|
|
5
|
+
//#region src/adapters/stdio.ts
|
|
6
|
+
/**
|
|
7
|
+
* Local stdio server for Claude Code, Cursor, Claude Desktop, etc. No access token is needed: the
|
|
8
|
+
* client launches this process itself. The key can also come from a file via
|
|
9
|
+
* GOOGLE_APPLICATION_CREDENTIALS.
|
|
10
|
+
*/
|
|
11
|
+
async function runStdio(opts = {}) {
|
|
12
|
+
const env = { ...opts.env ?? process.env };
|
|
13
|
+
if (!env.GOOGLE_SERVICE_ACCOUNT_JSON && env.GOOGLE_APPLICATION_CREDENTIALS) try {
|
|
14
|
+
env.GOOGLE_SERVICE_ACCOUNT_JSON = readFileSync(env.GOOGLE_APPLICATION_CREDENTIALS, "utf8");
|
|
15
|
+
} catch (error) {
|
|
16
|
+
throw new SetupError(`Could not read GOOGLE_APPLICATION_CREDENTIALS (${env.GOOGLE_APPLICATION_CREDENTIALS}): ${error.message}`);
|
|
17
|
+
}
|
|
18
|
+
const loaded = loadConfig(env, { transport: "stdio" });
|
|
19
|
+
if (!loaded.ok) throw new SetupError(formatConfigErrors(loaded.errors));
|
|
20
|
+
const runtime = createRuntime(loaded.config, {
|
|
21
|
+
fetch: opts.fetch,
|
|
22
|
+
logWriter: stderrWriter,
|
|
23
|
+
logFields: { transport: "stdio" }
|
|
24
|
+
});
|
|
25
|
+
for (const warning of loaded.warnings) runtime.logger.warn(warning);
|
|
26
|
+
serveStdio(() => buildMcpServer({
|
|
27
|
+
tools: runtime.owner.tools,
|
|
28
|
+
ctx: runtime.owner.ctx,
|
|
29
|
+
logger: runtime.logger,
|
|
30
|
+
activity: runtime.activity,
|
|
31
|
+
client: "stdio"
|
|
32
|
+
}));
|
|
33
|
+
}
|
|
34
|
+
//#endregion
|
|
35
|
+
export { runStdio };
|
|
36
|
+
|
|
37
|
+
//# sourceMappingURL=stdio.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stdio.js","names":[],"sources":["../../src/adapters/stdio.ts"],"sourcesContent":["import { readFileSync } from 'node:fs';\nimport { serveStdio } from '@modelcontextprotocol/server/stdio';\nimport { formatConfigErrors, loadConfig, type Env } from '../core/config.js';\nimport { stderrWriter } from '../core/log.js';\nimport { buildMcpServer } from '../core/mcp.js';\nimport { createRuntime } from '../core/runtime.js';\nimport { SetupError } from './node-http.js';\n\n/**\n * Local stdio server for Claude Code, Cursor, Claude Desktop, etc. No access token is needed: the\n * client launches this process itself. The key can also come from a file via\n * GOOGLE_APPLICATION_CREDENTIALS.\n */\nexport async function runStdio(opts: { env?: Env; fetch?: typeof fetch } = {}): Promise<void> {\n const env = { ...(opts.env ?? process.env) };\n if (!env.GOOGLE_SERVICE_ACCOUNT_JSON && env.GOOGLE_APPLICATION_CREDENTIALS) {\n try {\n env.GOOGLE_SERVICE_ACCOUNT_JSON = readFileSync(env.GOOGLE_APPLICATION_CREDENTIALS, 'utf8');\n } catch (error) {\n throw new SetupError(\n `Could not read GOOGLE_APPLICATION_CREDENTIALS (${env.GOOGLE_APPLICATION_CREDENTIALS}): ${(error as Error).message}`,\n );\n }\n }\n\n const loaded = loadConfig(env, { transport: 'stdio' });\n if (!loaded.ok) throw new SetupError(formatConfigErrors(loaded.errors));\n\n // stdout carries the protocol; logs must go to stderr.\n const runtime = createRuntime(loaded.config, {\n fetch: opts.fetch,\n logWriter: stderrWriter,\n logFields: { transport: 'stdio' },\n });\n for (const warning of loaded.warnings) runtime.logger.warn(warning);\n\n serveStdio(() =>\n buildMcpServer({\n tools: runtime.owner!.tools,\n ctx: runtime.owner!.ctx,\n logger: runtime.logger,\n activity: runtime.activity,\n client: 'stdio',\n }),\n );\n}\n"],"mappings":";;;;;;;;;;AAaA,eAAsB,SAAS,OAA4C,CAAC,GAAkB;CAC5F,MAAM,MAAM,EAAE,GAAI,KAAK,OAAO,QAAQ,IAAK;CAC3C,IAAI,CAAC,IAAI,+BAA+B,IAAI,gCAC1C,IAAI;EACF,IAAI,8BAA8B,aAAa,IAAI,gCAAgC,MAAM;CAC3F,SAAS,OAAO;EACd,MAAM,IAAI,WACR,kDAAkD,IAAI,+BAA+B,KAAM,MAAgB,SAC7G;CACF;CAGF,MAAM,SAAS,WAAW,KAAK,EAAE,WAAW,QAAQ,CAAC;CACrD,IAAI,CAAC,OAAO,IAAI,MAAM,IAAI,WAAW,mBAAmB,OAAO,MAAM,CAAC;CAGtE,MAAM,UAAU,cAAc,OAAO,QAAQ;EAC3C,OAAO,KAAK;EACZ,WAAW;EACX,WAAW,EAAE,WAAW,QAAQ;CAClC,CAAC;CACD,KAAK,MAAM,WAAW,OAAO,UAAU,QAAQ,OAAO,KAAK,OAAO;CAElE,iBACE,eAAe;EACb,OAAO,QAAQ,MAAO;EACtB,KAAK,QAAQ,MAAO;EACpB,QAAQ,QAAQ;EAChB,UAAU,QAAQ;EAClB,QAAQ;CACV,CAAC,CACH;AACF"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { t as createApp } from "../app-DhK9JWEH.js";
|
|
2
|
+
//#region src/adapters/vercel.ts
|
|
3
|
+
let app;
|
|
4
|
+
/**
|
|
5
|
+
* Vercel Function (Node.js runtime, Fluid Compute) using the web-standard `fetch` export.
|
|
6
|
+
* `api/index.js` re-exports this, and vercel.json rewrites every path to it.
|
|
7
|
+
*/
|
|
8
|
+
var vercel_default = { fetch(request) {
|
|
9
|
+
app ??= createApp(process.env, { name: "vercel" });
|
|
10
|
+
return app.fetch(request);
|
|
11
|
+
} };
|
|
12
|
+
//#endregion
|
|
13
|
+
export { vercel_default as default };
|
|
14
|
+
|
|
15
|
+
//# sourceMappingURL=vercel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vercel.js","names":[],"sources":["../../src/adapters/vercel.ts"],"sourcesContent":["import { createApp, type App } from '../core/app.js';\n\nlet app: App | undefined;\n\n/**\n * Vercel Function (Node.js runtime, Fluid Compute) using the web-standard `fetch` export.\n * `api/index.js` re-exports this, and vercel.json rewrites every path to it.\n */\nexport default {\n fetch(request: Request): Promise<Response> {\n app ??= createApp(process.env, { name: 'vercel' });\n return app.fetch(request);\n },\n};\n"],"mappings":";;AAEA,IAAI;;;;;AAMJ,IAAA,iBAAe,EACb,MAAM,SAAqC;CACzC,QAAQ,UAAU,QAAQ,KAAK,EAAE,MAAM,SAAS,CAAC;CACjD,OAAO,IAAI,MAAM,OAAO;AAC1B,EACF"}
|