Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 17 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -748,15 +748,26 @@ use a **repository provider**. mcpproxy will:
- **Provider name** — e.g. `linkedin`.
- **Git URL** — `https://github.com/felipfr/linkedin-mcpserver` (https or ssh).
- **Ref** *(optional)* — branch, tag, or commit SHA. Defaults to the repo's default branch.
- **Build commands** — one per row, e.g. `npm install`, then `npm run build`.
- **Spawn command** — the stdio MCP launch command, e.g. `node dist/main.js`. Runs inside the workdir.
- **Build commands** — one per row. For most Node/TypeScript MCP repos: `npm install`, then `npm run build`. Click **⚡ Pre-fill Node/TS** to drop these in automatically along with the spawn command.
- **Spawn command** — the stdio MCP launch command. For the compiled-TS pattern above, use `node build/index.js` (the `npm run build` step compiles `src/*.ts` → `build/*.js`). Runs inside the workdir.
3. Click **Next** — mcpproxy clones, builds, and introspects. The tool list is auto-populated.

> **Recommended for Node/TypeScript repos** (covers `linkedin-mcpserver` and most fastmcp-style projects):
>
> | Field | Value |
> |---|---|
> | Build commands | `npm install`<br>`npm run build` |
> | Spawn command | `node build/index.js` |
>
> The **⚡ Pre-fill Node/TS** button in the wizard's Build commands header populates all three at once.

> **Do not** put `npm run start:dev`, `npm start`, or any other long-running server command in **Build commands** — those go in **Spawn command**. Build commands must terminate; mcpproxy enforces a `MCPPROXY_BUILD_TIMEOUT` (default 600s) and aborts a hanging build.

#### YAML produced

```yaml
package:
command: node dist/main.js # spawn command, run inside the workdir
command: node build/index.js # spawn command, run inside the workdir
repository:
url: https://github.com/felipfr/linkedin-mcpserver
ref: main # optional
Expand All @@ -765,9 +776,9 @@ repository:
- npm install
- npm run build
env_keys: # auto-discovered from .env.example
- LINKEDIN_EMAIL # values live in MCP_ENV_FILE
- LINKEDIN_PASSWORD # (the proxy's .env) and are written
- LINKEDIN_LI_AT # into <workdir>/.env on every build / spawn
- LINKEDIN_CLIENT_ID # values live in MCP_ENV_FILE
- LINKEDIN_CLIENT_SECRET # (the proxy's .env) and are written
# into <workdir>/.env on every build / spawn
tools:
- name: search_jobs # advertised as linkedin__search_jobs
description: Search LinkedIn job postings.
Expand Down
29 changes: 25 additions & 4 deletions frontend/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -1198,16 +1198,21 @@ async def index():
<input class="form-control font-monospace" id="wz-repo-ref" placeholder="main">
</div>
<div class="mb-3">
<label class="form-label">Build commands <span class="text-muted fw-normal" style="text-transform:none">run inside the cloned workdir, in order — must terminate</span></label>
<label class="form-label d-flex justify-content-between align-items-center">
<span>Build commands <span class="text-muted fw-normal" style="text-transform:none">run inside the cloned workdir, in order — must terminate</span></span>
<button class="btn btn-sm btn-outline-secondary py-0" onclick="wzPrefillRepoNodeTs()" title="Pre-fill the Node/TypeScript defaults: npm install + npm run build, spawn node build/index.js">⚡ Pre-fill Node/TS</button>
</label>
<div id="wz-repo-builds-container"></div>
<button class="btn btn-sm btn-outline-secondary py-0 mt-1" onclick="wzAddRepoBuild()">+ Add command</button>
<div class="text-muted mt-1" style="font-size:.8em">e.g. <code>npm install</code>, <code>npm run build</code>. <b>Do not</b> put the long-running server start here (e.g. <code>npm run start:dev</code>) — that goes in <b>Spawn command</b>. Build commands re-run on every server start so ephemeral containers rebuild.</div>
<div class="text-muted mt-1" style="font-size:.8em">
<b>Recommended for Node/TypeScript repos</b>: <code>npm install</code> then <code>npm run build</code> (then spawn with <code>node build/index.js</code>). <b>Do not</b> put a long-running server start here (e.g. <code>npm run start:dev</code>) — that goes in <b>Spawn command</b>. Build commands re-run on every server start so ephemeral containers rebuild.
</div>
</div>
<div class="mb-3">
<label class="form-label">Spawn command *</label>
<input class="form-control font-monospace" id="wz-repo-cmd"
placeholder="node dist/main.js">
<div class="text-muted mt-1" style="font-size:.8em">The long-running command that launches the stdio MCP server, run from inside the workdir after the build commands complete.</div>
placeholder="node build/index.js">
<div class="text-muted mt-1" style="font-size:.8em">The long-running command that launches the stdio MCP server, run from inside the workdir after the build commands complete. Common values: <code>node build/index.js</code> (compiled TS), <code>npx tsx src/main.ts</code> (un-compiled TS), <code>python -m my_server</code>.</div>
</div>
<div class="text-muted" style="font-size:.8em">Clicking <b>Next</b> clones the repo, parses <code>.env.example</code> (so its keys appear as secrets on the next step), runs the build commands, then introspects the spawn command to populate the tool list. If the build fails because secrets aren't set yet, you can still continue — the next server restart will re-build with the secrets in place.</div>
<div id="wz-repo-result" class="mt-2"></div>
Expand Down Expand Up @@ -2090,6 +2095,22 @@ async def index():

function wzAddRepoBuild() { _wzListAdd('wz-repo-builds-container', 'npm install'); }

// One-click Node/TypeScript defaults — covers the common case (e.g. the
// linkedin-mcpserver / typical fastmcp-style TS repos).
function wzPrefillRepoNodeTs() {
const container = document.getElementById('wz-repo-builds-container');
container.innerHTML = '';
_wzListAdd('wz-repo-builds-container', 'npm install');
_wzListAdd('wz-repo-builds-container', 'npm run build');
// Populate the two input slots we just appended
const inputs = container.querySelectorAll('input');
if (inputs.length >= 2) {
inputs[0].value = 'npm install';
inputs[1].value = 'npm run build';
}
document.getElementById('wz-repo-cmd').value = 'node build/index.js';
}

function wzSelectType(type) {
wzType = type;
document.querySelectorAll('.wizard-choice').forEach(el => el.classList.remove('selected'));
Expand Down
Loading