@clickonsearch/linkedin-mcp-server 0.1.1 → 0.2.0

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/README.md CHANGED
@@ -52,9 +52,26 @@ LINKEDIN_CLIENT_ID=<id> LINKEDIN_CLIENT_SECRET=<secret> \
52
52
  npx @clickonsearch/linkedin-mcp-server
53
53
  ```
54
54
 
55
- It's now listening on `http://localhost:4300` for whatever agent you point
55
+ It's now listening on `http://127.0.0.1:4300` for whatever agent you point
56
56
  at it.
57
57
 
58
+ ### Letting another machine connect
59
+
60
+ By default only programs on the same computer can reach this server. To
61
+ allow others (an agent in a container, or on another machine), pick a
62
+ secret and set both:
63
+
64
+ ```bash
65
+ export LINKEDIN_MCP_TOKEN=$(openssl rand -hex 32)
66
+ BIND_HOST=0.0.0.0 npx @clickonsearch/linkedin-mcp-server
67
+ ```
68
+
69
+ Give `linkedin-agent` the same `LINKEDIN_MCP_TOKEN` and it sends it
70
+ automatically. The server refuses to start on any other address without a
71
+ token. Anyone holding the token can post to your LinkedIn feed as you, so
72
+ treat it like a password — and since it travels over plain HTTP, only use
73
+ this on a network you trust or behind TLS (for example a reverse proxy).
74
+
58
75
  ## What it exposes
59
76
 
60
77
  | Tool | What it does |
@@ -0,0 +1,16 @@
1
+ import type { RequestHandler } from "express";
2
+ export interface ListenConfig {
3
+ host: string;
4
+ /** Bearer token every caller must present. Always set when `host` isn't loopback. */
5
+ authToken?: string;
6
+ }
7
+ export declare function isLoopbackHost(host: string): boolean;
8
+ /**
9
+ * Listens on loopback only unless BIND_HOST says otherwise, and refuses to
10
+ * listen on anything else without a token — the MCP tools can publish
11
+ * posts to your LinkedIn feed as you, so a network-reachable server with no
12
+ * caller authentication is never acceptable.
13
+ */
14
+ export declare function resolveListenConfig(env?: NodeJS.ProcessEnv): ListenConfig;
15
+ /** Rejects any request without `Authorization: Bearer <token>`. Compared in constant time. */
16
+ export declare function requireBearerToken(token: string): RequestHandler;
package/dist/access.js ADDED
@@ -0,0 +1,40 @@
1
+ import { createHash, timingSafeEqual } from "node:crypto";
2
+ const LOOPBACK_HOSTS = ["127.0.0.1", "localhost", "::1"];
3
+ const MIN_TOKEN_LENGTH = 16;
4
+ export function isLoopbackHost(host) {
5
+ return LOOPBACK_HOSTS.includes(host);
6
+ }
7
+ /**
8
+ * Listens on loopback only unless BIND_HOST says otherwise, and refuses to
9
+ * listen on anything else without a token — the MCP tools can publish
10
+ * posts to your LinkedIn feed as you, so a network-reachable server with no
11
+ * caller authentication is never acceptable.
12
+ */
13
+ export function resolveListenConfig(env = process.env) {
14
+ const host = env.BIND_HOST || "127.0.0.1";
15
+ const authToken = env.LINKEDIN_MCP_TOKEN || undefined;
16
+ if (authToken && authToken.length < MIN_TOKEN_LENGTH) {
17
+ throw new Error(`LINKEDIN_MCP_TOKEN must be at least ${MIN_TOKEN_LENGTH} characters (try: openssl rand -hex 32)`);
18
+ }
19
+ if (!isLoopbackHost(host) && !authToken) {
20
+ throw new Error(`Refusing to listen on ${host} without authentication. Set LINKEDIN_MCP_TOKEN ` +
21
+ `(try: openssl rand -hex 32), or unset BIND_HOST to listen on 127.0.0.1 only.`);
22
+ }
23
+ return { host, authToken };
24
+ }
25
+ function sha256(value) {
26
+ return createHash("sha256").update(value).digest();
27
+ }
28
+ /** Rejects any request without `Authorization: Bearer <token>`. Compared in constant time. */
29
+ export function requireBearerToken(token) {
30
+ const expected = sha256(token);
31
+ return (req, res, next) => {
32
+ const match = /^Bearer\s+(.+)$/i.exec(req.headers.authorization ?? "");
33
+ if (match && timingSafeEqual(sha256(match[1]), expected)) {
34
+ next();
35
+ return;
36
+ }
37
+ res.status(401).set("WWW-Authenticate", "Bearer").json({ error: "unauthorized" });
38
+ };
39
+ }
40
+ //# sourceMappingURL=access.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"access.js","sourceRoot":"","sources":["../src/access.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAG1D,MAAM,cAAc,GAAG,CAAC,WAAW,EAAE,WAAW,EAAE,KAAK,CAAC,CAAC;AACzD,MAAM,gBAAgB,GAAG,EAAE,CAAC;AAQ5B,MAAM,UAAU,cAAc,CAAC,IAAY;IACzC,OAAO,cAAc,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;AACvC,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,mBAAmB,CAAC,MAAyB,OAAO,CAAC,GAAG;IACtE,MAAM,IAAI,GAAG,GAAG,CAAC,SAAS,IAAI,WAAW,CAAC;IAC1C,MAAM,SAAS,GAAG,GAAG,CAAC,kBAAkB,IAAI,SAAS,CAAC;IAEtD,IAAI,SAAS,IAAI,SAAS,CAAC,MAAM,GAAG,gBAAgB,EAAE,CAAC;QACrD,MAAM,IAAI,KAAK,CAAC,uCAAuC,gBAAgB,yCAAyC,CAAC,CAAC;IACpH,CAAC;IACD,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;QACxC,MAAM,IAAI,KAAK,CACb,yBAAyB,IAAI,kDAAkD;YAC7E,8EAA8E,CACjF,CAAC;IACJ,CAAC;IAED,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;AAC7B,CAAC;AAED,SAAS,MAAM,CAAC,KAAa;IAC3B,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,EAAE,CAAC;AACrD,CAAC;AAED,8FAA8F;AAC9F,MAAM,UAAU,kBAAkB,CAAC,KAAa;IAC9C,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IAE/B,OAAO,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;QACxB,MAAM,KAAK,GAAG,kBAAkB,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,aAAa,IAAI,EAAE,CAAC,CAAC;QACvE,IAAI,KAAK,IAAI,eAAe,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,EAAE,CAAC;YACzD,IAAI,EAAE,CAAC;YACP,OAAO;QACT,CAAC;QACD,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,kBAAkB,EAAE,QAAQ,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,cAAc,EAAE,CAAC,CAAC;IACpF,CAAC,CAAC;AACJ,CAAC"}
package/dist/auth.js CHANGED
@@ -85,6 +85,10 @@ export class TokenManager {
85
85
  throw new Error("LinkedIn access token has expired. LinkedIn only issues refresh tokens to apps approved for " +
86
86
  'offline access; without one, re-run "npm run authorize" to get a new token.');
87
87
  }
88
+ if (!this.config.clientId || !this.config.clientSecret) {
89
+ throw new Error("LinkedIn access token needs refreshing, but LINKEDIN_CLIENT_ID/LINKEDIN_CLIENT_SECRET aren't " +
90
+ 'set. Add them to your .env, or re-run "npm run authorize" to get a fresh token.');
91
+ }
88
92
  this.token = await refreshAccessToken(this.config, this.token.refreshToken);
89
93
  await saveToken(this.tokenPath, this.token);
90
94
  }
package/dist/auth.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAEvD,MAAM,iBAAiB,GAAG,iDAAiD,CAAC;AAC5E,MAAM,SAAS,GAAG,+CAA+C,CAAC;AAyBlE,MAAM,UAAU,qBAAqB,CAAC,MAA2B,EAAE,KAAa;IAC9E,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,iBAAiB,CAAC,CAAC;IACvC,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,eAAe,EAAE,MAAM,CAAC,CAAC;IAC9C,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,WAAW,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;IACnD,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,cAAc,EAAE,MAAM,CAAC,WAAW,CAAC,CAAC;IACzD,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IACrC,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IACvD,OAAO,GAAG,CAAC,QAAQ,EAAE,CAAC;AACxB,CAAC;AAED,KAAK,UAAU,YAAY,CAAC,IAAqB;IAC/C,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,SAAS,EAAE;QACjC,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,EAAE,cAAc,EAAE,mCAAmC,EAAE;QAChE,IAAI;KACL,CAAC,CAAC;IAEH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAC,kCAAkC,GAAG,CAAC,MAAM,IAAI,MAAM,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;IACtF,CAAC;IAED,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAkB,CAAC;IACjD,OAAO;QACL,WAAW,EAAE,IAAI,CAAC,YAAY;QAC9B,YAAY,EAAE,IAAI,CAAC,aAAa;QAChC,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,UAAU,GAAG,IAAI;QAC9C,KAAK,EAAE,IAAI,CAAC,KAAK;KAClB,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,MAA2B,EAAE,IAAY;IAC5E,OAAO,YAAY,CACjB,IAAI,eAAe,CAAC;QAClB,UAAU,EAAE,oBAAoB;QAChC,IAAI;QACJ,YAAY,EAAE,MAAM,CAAC,WAAW;QAChC,SAAS,EAAE,MAAM,CAAC,QAAQ;QAC1B,aAAa,EAAE,MAAM,CAAC,YAAY;KACnC,CAAC,CACH,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,MAA2B,EAAE,YAAoB;IACxF,MAAM,KAAK,GAAG,MAAM,YAAY,CAC9B,IAAI,eAAe,CAAC;QAClB,UAAU,EAAE,eAAe;QAC3B,aAAa,EAAE,YAAY;QAC3B,SAAS,EAAE,MAAM,CAAC,QAAQ;QAC1B,aAAa,EAAE,MAAM,CAAC,YAAY;KACnC,CAAC,CACH,CAAC;IACF,uFAAuF;IACvF,OAAO,EAAE,GAAG,KAAK,EAAE,YAAY,EAAE,KAAK,CAAC,YAAY,IAAI,YAAY,EAAE,CAAC;AACxE,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,IAAY;IAC1C,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,CAAgB,CAAC;IAClE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,IAAY,EAAE,KAAkB;IAC9D,MAAM,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;AACjE,CAAC;AAED;;;;;;GAMG;AACH,MAAM,OAAO,YAAY;IAIJ;IACA;IAJX,KAAK,CAAe;IAE5B,YACmB,MAA2B,EAC3B,SAAiB;QADjB,WAAM,GAAN,MAAM,CAAqB;QAC3B,cAAS,GAAT,SAAS,CAAQ;IACjC,CAAC;IAEJ,KAAK,CAAC,mBAAmB;QACvB,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;YAChB,IAAI,CAAC,KAAK,GAAG,MAAM,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAC/C,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;YAChB,MAAM,IAAI,KAAK,CACb,+FAA+F,CAChG,CAAC;QACJ,CAAC;QAED,MAAM,YAAY,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,MAAM,CAAC;QAChE,IAAI,YAAY,EAAE,CAAC;YACjB,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,YAAY,EAAE,CAAC;gBAC7B,MAAM,IAAI,KAAK,CACb,8FAA8F;oBAC5F,6EAA6E,CAChF,CAAC;YACJ,CAAC;YACD,IAAI,CAAC,KAAK,GAAG,MAAM,kBAAkB,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;YAC5E,MAAM,SAAS,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;QAC9C,CAAC;QAED,OAAO,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC;IAChC,CAAC;CACF"}
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"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"}
package/dist/cli.js CHANGED
@@ -3,40 +3,42 @@ import "dotenv/config";
3
3
  import { TokenManager } from "./auth.js";
4
4
  import { LinkedInClient } from "./linkedin.js";
5
5
  import { createServer } from "./server.js";
6
- function requireEnv(name) {
7
- const value = process.env[name];
8
- if (!value) {
9
- throw new Error(`Missing ${name} environment variable`);
10
- }
11
- return value;
12
- }
6
+ import { resolveListenConfig } from "./access.js";
7
+ /**
8
+ * clientId/clientSecret are only needed to refresh an expiring token (see
9
+ * TokenManager.getValidAccessToken) — a still-valid saved token needs
10
+ * neither, so this intentionally doesn't require them at startup.
11
+ */
13
12
  function loadConfig() {
14
13
  return {
15
- clientId: requireEnv("LINKEDIN_CLIENT_ID"),
16
- clientSecret: requireEnv("LINKEDIN_CLIENT_SECRET"),
14
+ clientId: process.env.LINKEDIN_CLIENT_ID ?? "",
15
+ clientSecret: process.env.LINKEDIN_CLIENT_SECRET ?? "",
17
16
  redirectUri: process.env.LINKEDIN_REDIRECT_URI ?? "http://localhost:3300/callback",
18
17
  scopes: (process.env.LINKEDIN_SCOPES ?? "openid profile email w_member_social").split(" "),
19
18
  };
20
19
  }
21
20
  async function main() {
22
- let config;
21
+ let listen;
23
22
  try {
24
- config = loadConfig();
23
+ listen = resolveListenConfig();
25
24
  }
26
25
  catch (error) {
27
26
  console.error(error instanceof Error ? error.message : String(error));
28
27
  process.exitCode = 1;
29
28
  return;
30
29
  }
30
+ const config = loadConfig();
31
31
  const tokenPath = process.env.LINKEDIN_TOKEN_PATH ?? "./linkedin-token.json";
32
32
  const port = Number(process.env.PORT ?? 4300);
33
33
  const tokens = new TokenManager(config, tokenPath);
34
34
  const linkedin = new LinkedInClient(tokens);
35
- const app = createServer(linkedin);
36
- app.listen(port, () => {
37
- console.error(`linkedin-mcp-server listening on http://localhost:${port}`);
38
- console.error(` MCP endpoint: POST http://localhost:${port}/mcp`);
39
- console.error(` Health: GET http://localhost:${port}/health`);
35
+ const app = createServer(linkedin, listen);
36
+ app.listen(port, listen.host, () => {
37
+ const origin = `http://${listen.host.includes(":") ? `[${listen.host}]` : listen.host}:${port}`;
38
+ console.error(`linkedin-mcp-server listening on ${origin}`);
39
+ console.error(` MCP endpoint: POST ${origin}/mcp`);
40
+ console.error(` Health: GET ${origin}/health`);
41
+ console.error(listen.authToken ? " Auth: bearer token required (LINKEDIN_MCP_TOKEN)" : " Auth: none (loopback only)");
40
42
  console.error(` If tools fail with "Not authorized yet", run: npm run authorize`);
41
43
  });
42
44
  }
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,eAAe,CAAC;AACvB,OAAO,EAAE,YAAY,EAA4B,MAAM,WAAW,CAAC;AACnE,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,SAAS,UAAU,CAAC,IAAY;IAC9B,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAChC,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CAAC,WAAW,IAAI,uBAAuB,CAAC,CAAC;IAC1D,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,UAAU;IACjB,OAAO;QACL,QAAQ,EAAE,UAAU,CAAC,oBAAoB,CAAC;QAC1C,YAAY,EAAE,UAAU,CAAC,wBAAwB,CAAC;QAClD,WAAW,EAAE,OAAO,CAAC,GAAG,CAAC,qBAAqB,IAAI,gCAAgC;QAClF,MAAM,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,sCAAsC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC;KAC3F,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,IAAI;IACjB,IAAI,MAA2B,CAAC;IAChC,IAAI,CAAC;QACH,MAAM,GAAG,UAAU,EAAE,CAAC;IACxB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;QACtE,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;QACrB,OAAO;IACT,CAAC;IAED,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,mBAAmB,IAAI,uBAAuB,CAAC;IAC7E,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,IAAI,CAAC,CAAC;IAE9C,MAAM,MAAM,GAAG,IAAI,YAAY,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IACnD,MAAM,QAAQ,GAAG,IAAI,cAAc,CAAC,MAAM,CAAC,CAAC;IAC5C,MAAM,GAAG,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAC;IAEnC,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,GAAG,EAAE;QACpB,OAAO,CAAC,KAAK,CAAC,qDAAqD,IAAI,EAAE,CAAC,CAAC;QAC3E,OAAO,CAAC,KAAK,CAAC,yCAAyC,IAAI,MAAM,CAAC,CAAC;QACnE,OAAO,CAAC,KAAK,CAAC,yCAAyC,IAAI,SAAS,CAAC,CAAC;QACtE,OAAO,CAAC,KAAK,CAAC,mEAAmE,CAAC,CAAC;IACrF,CAAC,CAAC,CAAC;AACL,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACrB,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACrB,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;AACvB,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,eAAe,CAAC;AACvB,OAAO,EAAE,YAAY,EAA4B,MAAM,WAAW,CAAC;AACnE,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,mBAAmB,EAAqB,MAAM,aAAa,CAAC;AAErE;;;;GAIG;AACH,SAAS,UAAU;IACjB,OAAO;QACL,QAAQ,EAAE,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,EAAE;QAC9C,YAAY,EAAE,OAAO,CAAC,GAAG,CAAC,sBAAsB,IAAI,EAAE;QACtD,WAAW,EAAE,OAAO,CAAC,GAAG,CAAC,qBAAqB,IAAI,gCAAgC;QAClF,MAAM,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,sCAAsC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC;KAC3F,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,IAAI;IACjB,IAAI,MAAoB,CAAC;IACzB,IAAI,CAAC;QACH,MAAM,GAAG,mBAAmB,EAAE,CAAC;IACjC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;QACtE,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;QACrB,OAAO;IACT,CAAC;IAED,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAC5B,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,mBAAmB,IAAI,uBAAuB,CAAC;IAC7E,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,IAAI,CAAC,CAAC;IAE9C,MAAM,MAAM,GAAG,IAAI,YAAY,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IACnD,MAAM,QAAQ,GAAG,IAAI,cAAc,CAAC,MAAM,CAAC,CAAC;IAC5C,MAAM,GAAG,GAAG,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IAE3C,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,GAAG,EAAE;QACjC,MAAM,MAAM,GAAG,UAAU,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,IAAI,IAAI,EAAE,CAAC;QAChG,OAAO,CAAC,KAAK,CAAC,oCAAoC,MAAM,EAAE,CAAC,CAAC;QAC5D,OAAO,CAAC,KAAK,CAAC,wBAAwB,MAAM,MAAM,CAAC,CAAC;QACpD,OAAO,CAAC,KAAK,CAAC,wBAAwB,MAAM,SAAS,CAAC,CAAC;QACvD,OAAO,CAAC,KAAK,CACX,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,4DAA4D,CAAC,CAAC,CAAC,sCAAsC,CACzH,CAAC;QACF,OAAO,CAAC,KAAK,CAAC,mEAAmE,CAAC,CAAC;IACrF,CAAC,CAAC,CAAC;AACL,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACrB,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACrB,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;AACvB,CAAC,CAAC,CAAC"}
package/dist/index.d.ts CHANGED
@@ -3,3 +3,5 @@ export type { LinkedInOAuthConfig, StoredToken } from "./auth.js";
3
3
  export { LinkedInClient } from "./linkedin.js";
4
4
  export type { LinkedInProfile } from "./linkedin.js";
5
5
  export { createServer } from "./server.js";
6
+ export { resolveListenConfig, requireBearerToken, isLoopbackHost } from "./access.js";
7
+ export type { ListenConfig } from "./access.js";
package/dist/index.js CHANGED
@@ -1,4 +1,5 @@
1
1
  export { TokenManager, buildAuthorizationUrl, exchangeCodeForToken, refreshAccessToken, loadToken, saveToken } from "./auth.js";
2
2
  export { LinkedInClient } from "./linkedin.js";
3
3
  export { createServer } from "./server.js";
4
+ export { resolveListenConfig, requireBearerToken, isLoopbackHost } from "./access.js";
4
5
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAEhI,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAE/C,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAEhI,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAE/C,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC"}
package/dist/server.d.ts CHANGED
@@ -1,10 +1,16 @@
1
1
  import type { Express } from "express";
2
2
  import type { LinkedInClient } from "./linkedin.js";
3
+ import { type ListenConfig } from "./access.js";
3
4
  /**
4
5
  * Builds the Express app: `POST /mcp` is the stateless MCP endpoint (a
5
6
  * fresh McpServer per request, matching the SDK's own reference server),
6
7
  * `GET /health` is a liveness check. Unlike whatsapp-mcp-server, there's no
7
8
  * push/events stream here — LinkedIn's API is pure request/response, there's
8
9
  * nothing to watch for.
10
+ *
11
+ * `listen` must match what the caller passes to `app.listen`. The SDK's Host
12
+ * header check only guards browser-origin (DNS rebinding) attacks and is
13
+ * trivially bypassed by a network client sending `Host: localhost`, so it
14
+ * is not authentication: `authToken`, when set, gates every route.
9
15
  */
10
- export declare function createServer(linkedin: LinkedInClient): Express;
16
+ export declare function createServer(linkedin: LinkedInClient, listen?: ListenConfig): Express;
package/dist/server.js CHANGED
@@ -2,6 +2,7 @@ import * as z from "zod/v4";
2
2
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
3
3
  import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
4
4
  import { createMcpExpressApp } from "@modelcontextprotocol/sdk/server/express.js";
5
+ import { requireBearerToken } from "./access.js";
5
6
  function buildMcpServer(linkedin) {
6
7
  const server = new McpServer({ name: "linkedin-mcp-server", version: "0.1.0" }, { capabilities: {} });
7
8
  server.registerTool("get_profile", { description: "Get the authenticated LinkedIn member's basic profile (name, email, picture)", inputSchema: {} }, async () => {
@@ -23,9 +24,17 @@ function buildMcpServer(linkedin) {
23
24
  * `GET /health` is a liveness check. Unlike whatsapp-mcp-server, there's no
24
25
  * push/events stream here — LinkedIn's API is pure request/response, there's
25
26
  * nothing to watch for.
27
+ *
28
+ * `listen` must match what the caller passes to `app.listen`. The SDK's Host
29
+ * header check only guards browser-origin (DNS rebinding) attacks and is
30
+ * trivially bypassed by a network client sending `Host: localhost`, so it
31
+ * is not authentication: `authToken`, when set, gates every route.
26
32
  */
27
- export function createServer(linkedin) {
28
- const app = createMcpExpressApp();
33
+ export function createServer(linkedin, listen = { host: "127.0.0.1" }) {
34
+ const app = createMcpExpressApp({ host: listen.host });
35
+ if (listen.authToken) {
36
+ app.use(requireBearerToken(listen.authToken));
37
+ }
29
38
  app.post("/mcp", async (req, res) => {
30
39
  try {
31
40
  const server = buildMcpServer(linkedin);
@@ -1 +1 @@
1
- {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clickonsearch/linkedin-mcp-server",
3
- "version": "0.1.1",
3
+ "version": "0.2.0",
4
4
  "description": "MCP server for a personal LinkedIn account via LinkedIn's OAuth 2.0 API: read your own profile and publish posts to your feed.",
5
5
  "type": "module",
6
6
  "license": "MIT",