@agentcairn/mcp-server 0.1.4 → 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/dist/authn.d.ts CHANGED
@@ -1,9 +1,10 @@
1
1
  import type { IncomingMessage } from 'node:http';
2
- import { type Brain } from '@agentcairn/core';
2
+ import { type Brain, type Principal } from '@agentcairn/core';
3
3
  export type AuthResult = {
4
4
  ok: true;
5
5
  kind: 'env' | 'managed' | 'open';
6
6
  name: string;
7
+ principal: Principal;
7
8
  } | {
8
9
  ok: false;
9
10
  reason: 'missing' | 'invalid' | 'no_tokens';
@@ -29,8 +30,13 @@ export declare class Authenticator {
29
30
  private readonly bad;
30
31
  private readonly touched;
31
32
  private managed;
33
+ private solo;
32
34
  constructor(brain: Brain, options?: AuthOptions, clock?: () => number, log?: (m: string) => void);
33
35
  invalidate(): void;
36
+ /** One active user or none: solo mode. Cached briefly; invalidate() refreshes it when users change. */
37
+ private isSolo;
38
+ /** Who a request acts as. A token acts as its creator; the old shared token and open mode act as the first admin. */
39
+ private principalFor;
34
40
  private hasManagedTokens;
35
41
  check(req: IncomingMessage): Promise<AuthResult>;
36
42
  private touch;
package/dist/authn.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { createHash, timingSafeEqual } from 'node:crypto';
2
- import { countActiveTokens, findApiToken, touchApiToken } from '@agentcairn/core';
2
+ import { SOLO_PRINCIPAL, countActiveTokens, countActiveUsers, findApiToken, firstAdmin, principalOf, touchApiToken, } from '@agentcairn/core';
3
3
  const digest = (s) => createHash('sha256').update(s).digest();
4
4
  const POSITIVE_MS = 30_000;
5
5
  const NEGATIVE_MS = 5_000;
@@ -19,6 +19,7 @@ export class Authenticator {
19
19
  bad = new Map();
20
20
  touched = new Map();
21
21
  managed;
22
+ solo;
22
23
  constructor(brain, options = {}, clock = Date.now, log = () => undefined) {
23
24
  this.brain = brain;
24
25
  this.options = options;
@@ -29,6 +30,27 @@ export class Authenticator {
29
30
  this.good.clear();
30
31
  this.bad.clear();
31
32
  this.managed = undefined;
33
+ this.solo = undefined;
34
+ }
35
+ /** One active user or none: solo mode. Cached briefly; invalidate() refreshes it when users change. */
36
+ async isSolo() {
37
+ const now = this.clock();
38
+ if (this.solo && this.solo.until > now)
39
+ return this.solo.value;
40
+ const value = (await countActiveUsers(this.brain)) <= 1;
41
+ this.solo = { value, until: now + NEGATIVE_MS };
42
+ return value;
43
+ }
44
+ /** Who a request acts as. A token acts as its creator; the old shared token and open mode act as the first admin. */
45
+ async principalFor(user, scope = null) {
46
+ const solo = await this.isSolo();
47
+ const acting = user ?? (await firstAdmin(this.brain));
48
+ if (!acting)
49
+ return scope ? { ...SOLO_PRINCIPAL, scope } : SOLO_PRINCIPAL;
50
+ if (acting.status === 'disabled')
51
+ return null;
52
+ const principal = principalOf(acting, solo);
53
+ return scope ? { ...principal, scope } : principal;
32
54
  }
33
55
  async hasManagedTokens() {
34
56
  const now = this.clock();
@@ -40,14 +62,17 @@ export class Authenticator {
40
62
  }
41
63
  async check(req) {
42
64
  if (this.options.noAuth)
43
- return { ok: true, kind: 'open', name: 'open' };
65
+ return { ok: true, kind: 'open', name: 'open', principal: (await this.principalFor(null)) ?? SOLO_PRINCIPAL };
44
66
  const header = req.headers.authorization ?? '';
45
67
  const bearer = header.startsWith('Bearer ') ? header.slice(7).trim() : '';
46
68
  if (bearer && this.options.envToken) {
47
69
  const a = digest(bearer);
48
70
  const b = digest(this.options.envToken);
49
- if (timingSafeEqual(a, b))
50
- return { ok: true, kind: 'env', name: 'env' };
71
+ if (timingSafeEqual(a, b)) {
72
+ const principal = await this.principalFor(null);
73
+ if (principal)
74
+ return { ok: true, kind: 'env', name: 'env', principal };
75
+ }
51
76
  }
52
77
  if (bearer) {
53
78
  const key = createHash('sha256').update(bearer).digest('hex');
@@ -55,15 +80,16 @@ export class Authenticator {
55
80
  const cached = this.good.get(key);
56
81
  if (cached && cached.until > now) {
57
82
  this.touch(cached.id, now);
58
- return { ok: true, kind: 'managed', name: cached.name };
83
+ return { ok: true, kind: 'managed', name: cached.name, principal: cached.principal };
59
84
  }
60
85
  if ((this.bad.get(key) ?? 0) > now)
61
86
  return { ok: false, reason: 'invalid' };
62
87
  const found = await findApiToken(this.brain, bearer);
63
- if (found) {
64
- this.good.set(key, { ...found, until: now + POSITIVE_MS });
88
+ const principal = found ? await this.principalFor(found.user, found.scope) : null;
89
+ if (found && principal) {
90
+ this.good.set(key, { id: found.id, name: found.name, principal, until: now + POSITIVE_MS });
65
91
  this.touch(found.id, now);
66
- return { ok: true, kind: 'managed', name: found.name };
92
+ return { ok: true, kind: 'managed', name: found.name, principal };
67
93
  }
68
94
  if (this.bad.size > 500)
69
95
  this.bad.clear();
package/dist/authn.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"authn.js","sourceRoot":"","sources":["../src/authn.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"authn.js","sourceRoot":"","sources":["../src/authn.ts"],"names":[],"mappings":"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"}
package/dist/context.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { type Brain, type ProjectHint, type ResolvedProject } from '@agentcairn/core';
1
+ import { type Action, type Brain, type Principal, type ProjectHint, type ResolvedProject } from '@agentcairn/core';
2
2
  /**
3
3
  * Where the project comes from. A local (stdio) server reads the folder the
4
4
  * agent works in; a remote server cannot, so the client says who it is.
@@ -21,10 +21,14 @@ export declare class BrainContext {
21
21
  private readonly clientName;
22
22
  /** Told which project each call resolved to (the dashboard shows it). */
23
23
  private readonly onProject;
24
+ /** Who is asking. Every project use is checked against this. */
25
+ readonly principal: Principal;
24
26
  private schema;
25
27
  constructor(brain: Brain, scope: Scope, clientName?: () => string | undefined,
26
28
  /** Told which project each call resolved to (the dashboard shows it). */
27
- onProject?: (projectId: string) => void);
29
+ onProject?: (projectId: string) => void,
30
+ /** Who is asking. Every project use is checked against this. */
31
+ principal?: Principal);
28
32
  /** The folder, when the server can see one (stdio mode). */
29
33
  get cwd(): string | undefined;
30
34
  /** Creates the schema once; a failed attempt is retried on the next call. */
@@ -36,7 +40,10 @@ export declare class BrainContext {
36
40
  */
37
41
  project(options: {
38
42
  write: boolean;
43
+ action?: Action;
39
44
  }): Promise<ResolvedProject>;
45
+ /** First write from a repository nobody has a project for yet: a project owned by the caller, named after the repository. */
46
+ private createFromRemote;
40
47
  /**
41
48
  * Who wrote a memory. Locally the server reads git itself; remotely the
42
49
  * client's hook supplies the commit and author. Values that do not look like
package/dist/context.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { hostname } from 'node:os';
2
- import { RemoteConflictError, attachRemote, ensureProject, ensureSchema, getRepoState, resolveProject, resolveProjectFromHint, } from '@agentcairn/core';
2
+ import { AccessError, PENDING, ProjectNotFoundError, ProjectNameError, RemoteConflictError, SOLO_PRINCIPAL, attachRemote, authorize, createProject, ensureProject, ensureSchema, getRepoState, resolveProject, resolveProjectFromHint, } from '@agentcairn/core';
3
3
  const SHA = /^[0-9a-f]{7,40}$/i;
4
4
  /** Everything a tool call needs: the brain, which project, and who is asking. */
5
5
  export class BrainContext {
@@ -7,14 +7,18 @@ export class BrainContext {
7
7
  scope;
8
8
  clientName;
9
9
  onProject;
10
+ principal;
10
11
  schema;
11
12
  constructor(brain, scope, clientName = () => undefined,
12
13
  /** Told which project each call resolved to (the dashboard shows it). */
13
- onProject = () => undefined) {
14
+ onProject = () => undefined,
15
+ /** Who is asking. Every project use is checked against this. */
16
+ principal = SOLO_PRINCIPAL) {
14
17
  this.brain = brain;
15
18
  this.scope = scope;
16
19
  this.clientName = clientName;
17
20
  this.onProject = onProject;
21
+ this.principal = principal;
18
22
  }
19
23
  /** The folder, when the server can see one (stdio mode). */
20
24
  get cwd() {
@@ -37,22 +41,56 @@ export class BrainContext {
37
41
  await this.ready();
38
42
  const project = 'cwd' in this.scope
39
43
  ? await resolveProject(this.brain, this.scope.cwd)
40
- : await resolveProjectFromHint(this.brain, this.scope.hint);
44
+ : await resolveProjectFromHint(this.brain, this.scope.hint, this.principal);
41
45
  this.onProject(project.projectId);
42
- if (options.write && project.isNew && project.source === 'remote') {
43
- await ensureProject(this.brain, project.projectId);
44
- if (project.remoteHash) {
46
+ if (!project.isNew) {
47
+ await authorize(this.brain, this.principal, options.action ?? (options.write ? 'memory.write' : 'memory.read'), project.projectId);
48
+ return project;
49
+ }
50
+ if (options.write && project.source === 'remote') {
51
+ const created = await this.createFromRemote(project);
52
+ this.onProject(created.projectId);
53
+ return created;
54
+ }
55
+ // an explicit id or name is never created implicitly, and a project you cannot see reads as missing
56
+ if (options.write)
57
+ throw new ProjectNotFoundError(project.requested ?? project.projectId.replace(PENDING, ''));
58
+ return project;
59
+ }
60
+ /** First write from a repository nobody has a project for yet: a project owned by the caller, named after the repository. */
61
+ async createFromRemote(project) {
62
+ let id = project.projectId;
63
+ if (this.principal.scope && (this.principal.scope.projects || this.principal.scope.readOnly)) {
64
+ throw new AccessError('forbidden', project.suggestedName ?? 'project', 'project.update', 'scope');
65
+ }
66
+ if (this.principal.userId === SOLO_PRINCIPAL.userId) {
67
+ // before any account exists there is nobody to own it: the plain legacy form
68
+ id = `git-${project.remoteHash}`;
69
+ await ensureProject(this.brain, id);
70
+ }
71
+ else {
72
+ const base = project.suggestedName ?? 'project';
73
+ for (let n = 1;; n++) {
45
74
  try {
46
- await attachRemote(this.brain, project.projectId, project.remoteHash);
75
+ id = (await createProject(this.brain, this.principal.userId, n === 1 ? base : `${base} (${n})`)).id;
76
+ break;
47
77
  }
48
78
  catch (error) {
49
- if (!(error instanceof RemoteConflictError))
79
+ if (!(error instanceof ProjectNameError && error.code === 'exists') || n >= 20)
50
80
  throw error;
51
81
  }
52
82
  }
53
- return { ...project, isNew: false };
54
83
  }
55
- return project;
84
+ if (project.remoteHash) {
85
+ try {
86
+ await attachRemote(this.brain, id, project.remoteHash, { principal: this.principal });
87
+ }
88
+ catch (error) {
89
+ if (!(error instanceof RemoteConflictError))
90
+ throw error;
91
+ }
92
+ }
93
+ return { ...project, projectId: id, isNew: false };
56
94
  }
57
95
  /**
58
96
  * Who wrote a memory. Locally the server reads git itself; remotely the
@@ -1 +1 @@
1
- {"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"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"}