Commit graph

95 commits

Author SHA1 Message Date
Jonathan Amsterdam
92ee792363 internal/mcp: fix roots design
Minor changes to the roots part of the design.

Change-Id: I8125aecc5da297594f74d8d7dc5ef3d94dfa8519
Reviewed-on: https://go-review.googlesource.com/c/tools/+/671356
Reviewed-by: Robert Findley <rfindley@google.com>
TryBot-Bypass: Jonathan Amsterdam <jba@google.com>
2025-05-12 06:39:01 -07:00
Jonathan Amsterdam
b767218505 internal/mcp/design.md: minor changes
Fix typos and formatting, reword slightly.

Also, change names in the middleware section.

Change-Id: Ie86e5f633a07675ab188a8aaf70e51a48b0878bb
Reviewed-on: https://go-review.googlesource.com/c/tools/+/671555
Reviewed-by: Robert Findley <rfindley@google.com>
TryBot-Bypass: Jonathan Amsterdam <jba@google.com>
2025-05-09 12:29:46 -07:00
Rob Findley
0f2d85336d internal/mcp/design: weave discussion of differences with mcp-go
Put discussion of mcp-go up front, and address differences in the
individual sections. I think this leads to easier reading for the user
who is concerned about our divergence in design.

Change-Id: Ifd21f6b9eb570ad4a325b8a8800b7868dac12205
Reviewed-on: https://go-review.googlesource.com/c/tools/+/671556
TryBot-Bypass: Robert Findley <rfindley@google.com>
Reviewed-by: Jonathan Amsterdam <jba@google.com>
Commit-Queue: Robert Findley <rfindley@google.com>
2025-05-09 12:14:29 -07:00
Rob Findley
7df3da6467 internal/mcp/design: remove the protocol package; update tools
Per discussion, remove the separate protocol package in favor of a
single mcp package. Update the tools section accordingly, and add more
discussion about the decision of the NewTool API.

Change-Id: Ifb259555ca9d493ce63bc4f71e5f2fa295bdf09c
Reviewed-on: https://go-review.googlesource.com/c/tools/+/671496
TryBot-Bypass: Robert Findley <rfindley@google.com>
Commit-Queue: Robert Findley <rfindley@google.com>
Reviewed-by: Jonathan Amsterdam <jba@google.com>
2025-05-09 09:55:46 -07:00
Rob Findley
47f4506702 internal/design: minor cleanup; add 'errors' and 'ping' sections
Perform some minor cleanup:
- Resolve semantic conflicts updating ServerConnection->ServerSession
- Use 'go' code blocks throughout

Also, add brief sections discussing error handling and 'ping/keepalive'.

Change-Id: I9ee888a7f0506ca380c2d4d4f9965a4c399aac19
Reviewed-on: https://go-review.googlesource.com/c/tools/+/671495
Reviewed-by: Jonathan Amsterdam <jba@google.com>
Commit-Queue: Robert Findley <rfindley@google.com>
TryBot-Bypass: Robert Findley <rfindley@google.com>
2025-05-09 09:54:58 -07:00
Jonathan Amsterdam
d07cf5f246 internal/mcp/design.md: prompts and resources
Change-Id: I5663e14846e3a37bea6947a12fbe57117b07174b
Reviewed-on: https://go-review.googlesource.com/c/tools/+/671497
TryBot-Bypass: Jonathan Amsterdam <jba@google.com>
Reviewed-by: Robert Findley <rfindley@google.com>
2025-05-09 09:37:35 -07:00
Jonathan Amsterdam
d7848c9e90 internal/mcp: progress notifications
Change-Id: I3dad9326a88c14d08d62395f603862f71f887a75
Reviewed-on: https://go-review.googlesource.com/c/tools/+/671475
TryBot-Bypass: Jonathan Amsterdam <jba@google.com>
Reviewed-by: Robert Findley <rfindley@google.com>
2025-05-09 09:25:50 -07:00
Rob Findley
e2248b0f80 internal/mcp/design: add a section on cancellation
Change-Id: If18a7d8efa37a6f34ae42f4d1896464800ebcdc7
Reviewed-on: https://go-review.googlesource.com/c/tools/+/671435
Reviewed-by: Jonathan Amsterdam <jba@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
2025-05-09 08:10:55 -07:00
Rob Findley
c8966c94f3 internal/mcp/design: add section on clients and servers
After much deliberation, revert back to the symmetrical many-to-one form
of the client APIs. Every time I tried to write the asymmetrical form, I
couldn't justify it. Furthermore, I think the names 'ClientSession' and
'ServerSession' significantly clarify the meaning.

Change-Id: I5c5e1eaf0d5de5ac7c98dab7aad9c0f31c3ff4e1
Reviewed-on: https://go-review.googlesource.com/c/tools/+/671177
Auto-Submit: Robert Findley <rfindley@google.com>
Reviewed-by: Jonathan Amsterdam <jba@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
2025-05-09 08:10:30 -07:00
Jonathan Amsterdam
814865c687 internal/mcp/design.md: completions
Design for the completions feature.
Change-Id: Ia793091a10adb9c51472a9d3d4acdce8d6932536
Reviewed-on: https://go-review.googlesource.com/c/tools/+/671376
Reviewed-by: Robert Findley <rfindley@google.com>
TryBot-Bypass: Jonathan Amsterdam <jba@google.com>
2025-05-09 08:03:51 -07:00
Jonathan Amsterdam
62401f56bd internal/mcp/design.md: client features
Change-Id: Iaed3461bcb35ca65c3118cafa0a5bbddfbd41ecc
Reviewed-on: https://go-review.googlesource.com/c/tools/+/671375
Reviewed-by: Robert Findley <rfindley@google.com>
TryBot-Bypass: Jonathan Amsterdam <jba@google.com>
2025-05-09 08:03:31 -07:00
Jonathan Amsterdam
908c91313e internal/mcp: tool section of design
Describe our tool design. This is short because most of the interesting
part is in the JSON Schema section.

Change-Id: I017fca3055aef881285280a379e9f235bf95e75d
Reviewed-on: https://go-review.googlesource.com/c/tools/+/671355
Reviewed-by: Robert Findley <rfindley@google.com>
TryBot-Bypass: Jonathan Amsterdam <jba@google.com>
2025-05-09 08:03:14 -07:00
Jonathan Amsterdam
74880af5fb internal/mcp: JSON Schema design
Describe how we use JSON Schema.

Change-Id: I488a09854333ba7280401e3bed5f50f83f481cd2
Reviewed-on: https://go-review.googlesource.com/c/tools/+/671215
Reviewed-by: Robert Findley <rfindley@google.com>
TryBot-Bypass: Jonathan Amsterdam <jba@google.com>
2025-05-09 03:51:36 -07:00
Jonathan Amsterdam
8ea274d324 internal/mcp/design: describe mcp-go delta
Describe the differences with mcp-go, and justify our choices.

Change-Id: Ib9b7ed87b8038f0b7cbc0eeffc5d7a7075eeae30
Reviewed-on: https://go-review.googlesource.com/c/tools/+/671017
Reviewed-by: Robert Findley <rfindley@google.com>
TryBot-Bypass: Jonathan Amsterdam <jba@google.com>
2025-05-09 03:26:29 -07:00
Rob Findley
d174d6405a internal/mcp/design: discuss generated protocol types
Discuss generated protocol types, and expand on the section on package
layout to make it clearer how they fit in to the SDK.

Change-Id: I3beaa86c2396e0cee41dcc8eac06d93c54cb96df
Reviewed-on: https://go-review.googlesource.com/c/tools/+/671016
Reviewed-by: Jonathan Amsterdam <jba@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
2025-05-08 13:02:41 -07:00
Rob Findley
e0d4191c70 internal/mcp: a new extensibility point for HTTP transports
Expose the SSEServerTransport type, so that clients can customize the
handling of sessions and endpoints by writing their own HTTP handler.
This is similar to the behavior of the typescript SDK.

Also, finish documenting transports in the design doc.

Change-Id: Ief5aa8424ba2946a9615e366969a4750f40224a8
Reviewed-on: https://go-review.googlesource.com/c/tools/+/671015
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Jonathan Amsterdam <jba@google.com>
Auto-Submit: Robert Findley <rfindley@google.com>
2025-05-08 12:19:33 -07:00
Jonathan Amsterdam
12fa054310 jsonschema: resolve refs
Implement the $ref keyword, except for remote references (those
pointing outside the root schema).

Change-Id: Ia5ca88464e62e9c613970d8d9fcd1512ab288934
Reviewed-on: https://go-review.googlesource.com/c/tools/+/670775
Reviewed-by: Alan Donovan <adonovan@google.com>
Auto-Submit: Jonathan Amsterdam <jba@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
2025-05-08 08:56:49 -07:00
Jonathan Amsterdam
5bcbf820f2 internal/mcp/protocol: spell "Id" idiomatically
Enhance the generator so that it recognizes initialisms like "Id" and
writes them in all caps, as is idiomatic for Go.

Also, fix the import path of jsonschema in the generated code.

Change-Id: Ib12e9fbd543d360035d5e324f0aefca584ac7c85
Reviewed-on: https://go-review.googlesource.com/c/tools/+/670916
Auto-Submit: Jonathan Amsterdam <jba@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Robert Findley <rfindley@google.com>
2025-05-08 08:22:14 -07:00
Jonathan Amsterdam
f1015cdc35 internal/mcp/design: logging
Design for logging.

Change-Id: I787bb51318337bd09f973e04d0e4dbf526e09fb6
Reviewed-on: https://go-review.googlesource.com/c/tools/+/670935
Reviewed-by: Robert Findley <rfindley@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Sam Thanawalla <samthanawalla@google.com>
Auto-Submit: Jonathan Amsterdam <jba@google.com>
2025-05-08 08:16:01 -07:00
Jonathan Amsterdam
a88ab0dadc internal/mcp/jsonschema: make Schema.every fully recursive
s.every now visits the entire subtree of schemas at s, not only the
immediate children of s.

This re-introduces a tower: now of closures instead of iterators.
We could remove it having everyChild call every recursively instead
of returning, just passing f down all the way unwrapped.
But this is going to complicate the recursive function inside
resolveURIs, which needs to pass parent context down. It would have
the same problem that ast.Inspect has, and we'd have to adopt the same
solution, maintaining a stack explicitly.

I feel it's cleaner to keep the recursion simple at the cost of building
several closures. To do otherwise would be premature optimization.

Change-Id: Ic453cdaac482da8147dafc34b0117d25458d1c9d
Reviewed-on: https://go-review.googlesource.com/c/tools/+/670675
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Alan Donovan <adonovan@google.com>
2025-05-07 16:17:56 -07:00
Rob Findley
390d437d4f internal/mcp/design: start a full design doc, with stubs
Start writing up a formal design doc for an MCP SDK based on what we've
learned from the prototype. Include discussion of package layout,
jsonrpc2, and transport. Lay out the rest of the design sections,
leaving stub comments describing what they should cover.

Change-Id: Id0e5b408eac8c0acb5ef90a32d0d69473d8e83f0
Reviewed-on: https://go-review.googlesource.com/c/tools/+/670536
Reviewed-by: Jonathan Amsterdam <jba@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Sam Thanawalla <samthanawalla@google.com>
Auto-Submit: Robert Findley <rfindley@google.com>
2025-05-07 13:50:30 -07:00
Rob Findley
347a1a0078 internal/mcp: rename ClientConnection to ServerConnection
It's too confusing that you send server requests through the Client, and
send client requests through the ClientConnection. Rename
ClientConnection to ServerConnection, so that the types on the
server side of the control diagram start with 'Server'.

Change-Id: Idfd27af464a9296a2341cd23b2075cd9d0eb6b45
Reviewed-on: https://go-review.googlesource.com/c/tools/+/670538
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Robert Findley <rfindley@google.com>
Reviewed-by: Jonathan Amsterdam <jba@google.com>
2025-05-07 10:17:38 -07:00
Jonathan Amsterdam
e0e304e51e internal/mcp: rename Make* to New*
Change-Id: I8d3d2ca125b7c24dd265937c4fe910ea823ab811
Reviewed-on: https://go-review.googlesource.com/c/tools/+/670537
Reviewed-by: Robert Findley <rfindley@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
2025-05-07 09:32:55 -07:00
Jonathan Amsterdam
9031106300 jsonschema: implement JSON Pointers for schemas
Implement enough of the JSON Pointer spec to suffice for JSON Schema.

For details, see the comment at the top of json_pointer.go.

Change-Id: Ic297f1a1a08903b4b3c6666fe57ac1f45c96c0f7
Reviewed-on: https://go-review.googlesource.com/c/tools/+/670535
Reviewed-by: Alan Donovan <adonovan@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
2025-05-07 09:31:46 -07:00
Jonathan Amsterdam
435f5447df internal/mcp/jsonschema: support validating structs
The instance passed to Resolved.Validate can be a struct, or can
contain structs. A struct is treated like the JSON object that it
marshals to.

Also support pointers to any depth. That is, if an instance is a **int,
then Validate will treat it like an int (or nil). That won't happen if
the instance is unmarshaled into an `any`, but may if it's unmarshaled
into a struct.

Change-Id: I39f9af58028bd779887495754519615cd5dfb6c8
Reviewed-on: https://go-review.googlesource.com/c/tools/+/670395
Reviewed-by: Alan Donovan <adonovan@google.com>
Auto-Submit: Jonathan Amsterdam <jba@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
2025-05-06 15:48:51 -07:00
Jonathan Amsterdam
f8098af1c5 internal/mcp: NewClient takes Transport
Pass the client Transport to NewClient instead of Connect.
Combine the ConnectionOptions with the ClientOptions.

Change-Id: I3acd6cf6d5bf46666742f2a73e2acaef2057ea77
Reviewed-on: https://go-review.googlesource.com/c/tools/+/670215
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Robert Findley <rfindley@google.com>
2025-05-06 12:19:25 -07:00
Hongxiang Jiang
bc84c08031 internal/mcp: add README.md and CONTRIBUTING.md
Move examples from package doc to README.md with package decl and
imports to ensure it's compilable.

Move status of the package from package doc to README.md.

Add core concepts of MCP with example code snippets and testing
recommendations.

Change-Id: I5bf5000b922fa3942aba922713b12d0347295811
Reviewed-on: https://go-review.googlesource.com/c/tools/+/670316
Reviewed-by: Sam Thanawalla <samthanawalla@google.com>
Reviewed-by: Jonathan Amsterdam <jba@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
2025-05-06 11:40:21 -07:00
Rob Findley
8efb54691d internal/mcp/protocol: move out of mcp/internal, as it's used in the API
The generated protocol package is part of the SDK API, so it shouldn't
be internal.

Change-Id: I5306af48019b1599707b939b348eb6ae4f766ca9
Reviewed-on: https://go-review.googlesource.com/c/tools/+/670356
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Jonathan Amsterdam <jba@google.com>
2025-05-06 10:18:38 -07:00
Jonathan Amsterdam
5cc4e6ea54 jsonschema: resolve anchors
Change-Id: Ibe7d8df0a46d3e3a8b5d0651b1113a54e756c7df
Reviewed-on: https://go-review.googlesource.com/c/tools/+/669998
Reviewed-by: Alan Donovan <adonovan@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
2025-05-06 03:57:39 -07:00
Jonathan Amsterdam
0a79e67c62 jsonschema: resolve URIs for $id
Assign a base URI to every schema.

See the comment on resolveURIs for details.

Change-Id: I2332d825c486766832503cabdd0bf9d819171d53
Reviewed-on: https://go-review.googlesource.com/c/tools/+/669997
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Alan Donovan <adonovan@google.com>
2025-05-06 03:57:31 -07:00
Jonathan Amsterdam
15e0c9ef02 internal/mcp: move jsonschema out of mcp/internal
The jsonschema package is part of of the API of the mcp package,
so it should not be internal.

Change-Id: I9520797837329fc2cda09c2f46ec4d48d031b9d3
Reviewed-on: https://go-review.googlesource.com/c/tools/+/669996
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Robert Findley <rfindley@google.com>
2025-05-05 13:17:44 -07:00
Jonathan Amsterdam
3d33fafc5d jsonschema: pre-compile regexps
This is the first CL that deals with the process of preparing a schema for validation.

Perform some basic checks on the scheme. Along the way, compile regexps and store
them in the schema for use during validation.

Change-Id: I0e5e6ce28656dcecb6d2d4b2fdc98998fa05b6f1
Reviewed-on: https://go-review.googlesource.com/c/tools/+/669696
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Alan Donovan <adonovan@google.com>
2025-05-05 12:29:58 -07:00
Jonathan Amsterdam
cc7bdd8d43 jsonschema: better errors unmarshaling ints
Distinguish among non-numbers, non-integral floating-point values,
and unrepresentable integers.

Change-Id: I0d60b92d6b4dd0baa536476931eb75e42ed5366a
Reviewed-on: https://go-review.googlesource.com/c/tools/+/669695
Reviewed-by: Alan Donovan <adonovan@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
2025-05-05 12:29:51 -07:00
Jonathan Amsterdam
3e8ca36823 jsonschema: using hashing for uniqueItems
Determine if a slice contains unique items by hashing them.
This should take linear time on average, better than the previous
quadratic algorithm.

Change-Id: I8dc95bb6f29d802bdbc64bc7f7e698c71eae5ce7
Reviewed-on: https://go-review.googlesource.com/c/tools/+/669455
Reviewed-by: Alan Donovan <adonovan@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
2025-05-03 03:10:23 -07:00
Jonathan Amsterdam
7a76f3502a mcp: remove ServerConnection
Remove ServerConnection.
- It's not in typescript or mcpgo APIs.
- Amortizing a client over multiple servers doesn't have any value.

Change-Id: I725b42569733d6836864d96b16898a10ae91e570
Reviewed-on: https://go-review.googlesource.com/c/tools/+/669575
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Robert Findley <rfindley@google.com>
2025-05-02 13:30:38 -07:00
Jonathan Amsterdam
40185dd013 jsonschema: represent integer keywords as ints
Some JSON Schema keywords, like minLength, are logically integers.
The JSON Schema spec allows them to be written as floating-point
values with zero fractional part, which is a reasonable choice, since
JSON doesn't distinguish the two.

We could simply validate these fields as integers in the normal course
of events (namely, validating the schema against its meta-schema),
but this CL does a little better: it uses *int struct fields for
these keywords, preventing them from ever being non-integers.
The UnmarshalJSON method still accepts integral floating-point values.
Marshaling is unaffected, and the results don't change: encoding/json
has always marshaled integral floats without the decimal part.

Other choices:
- Leave them as float64: you could then get away with
    Schema{MinLength: Ptr(1.5)}
  and though you couldn't get far with that, it's still irksome.

- json.Number: same problem as float64, plus it's even harder to write
  as a literal.

- int64: now `Ptr(1)` doesn't work (it's a *int, not a *int64).
  Anyway, these keywords all compare against len(x) in Go, which
  is of type int.

Change-Id: Ie3f08bd8a5deaf2a21344d6ab873551c011b12d5
Reviewed-on: https://go-review.googlesource.com/c/tools/+/668315
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Robert Findley <rfindley@google.com>
2025-05-02 10:55:18 -07:00
Jonathan Amsterdam
0def4e0327 jsonschema: validate object keywords
Add validation for JSON objects (Go maps).

The map keys are called "properties."

As with arrays, annotations are needed to support the
unevaluatedProperties keyword.

Change-Id: Ia01f74300f4bcdbce94065572d83c46dfaa53ae7
Reviewed-on: https://go-review.googlesource.com/c/tools/+/668256
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Alan Donovan <adonovan@google.com>
2025-05-02 10:52:57 -07:00
Rob Findley
bf608eeeae internal/mcp: clean up handling of content
Add support for all content types, and formalize the conversion of
content to and from the wire format (as a discriminated union).

Change-Id: I93678ce98c02176a524d2c82425fb1267ad68bf0
Reviewed-on: https://go-review.googlesource.com/c/tools/+/669135
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Jonathan Amsterdam <jba@google.com>
Auto-Submit: Robert Findley <rfindley@google.com>
2025-05-01 19:15:30 -07:00
Rob Findley
af4d138732 internal/mcp: support prompts
Add support for 'prompts/list' and 'prompts/get', and registering
prompts on the server using AddPrompts. Add a 'MakePrompt' helper to
construct prompts from a prompt handler using reflection.

Change-Id: I479cb9c9b99313cca99640c1f5ea1939363759e6
Reviewed-on: https://go-review.googlesource.com/c/tools/+/669015
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Jonathan Amsterdam <jba@google.com>
2025-05-01 18:43:44 -07:00
Rob Findley
e082a340be internal/mcp: add tool and schema options
Implement variadic options for building tools and schemas, to allow
easier customization of tool input schemas.

Also, make fields required, unless they are marked as "omitempty".

Change-Id: I7a29258fae3ec5e7ea4906ed30ed6750979de962
Reviewed-on: https://go-review.googlesource.com/c/tools/+/668955
Reviewed-by: Jonathan Amsterdam <jba@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
2025-05-01 18:41:25 -07:00
Rob Findley
ffa7599a10 internal/mcp: add more package documentation, examples
Add more documentation for the mcp package, explaining how to create and
use Clients and Servers. Also add an example of using the SSEHandler to
crete an MCP server.

Change-Id: Ib327826b2cdb1e3418482551c65569ec6f01af33
Reviewed-on: https://go-review.googlesource.com/c/tools/+/668715
Reviewed-by: Jonathan Amsterdam <jba@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Neal Patel <nealpatel@google.com>
Auto-Submit: Robert Findley <rfindley@google.com>
2025-05-01 18:30:42 -07:00
Rob Findley
56ed3872f3 internal/mcp: add a command transport for connecting to a sidecar
Add a missing CommandTransport that communicates with a sidecar process
over newline-delimited stdin/stdout, the counterpart to the existing
StdIOTransport.

Add a test using the usual TestMain trick.

Change-Id: I170ba78faf6b6d7fca7da1af11bf92e919b11ed5
Reviewed-on: https://go-review.googlesource.com/c/tools/+/668895
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Jonathan Amsterdam <jba@google.com>
2025-05-01 17:43:04 -07:00
Jonathan Amsterdam
860a55afbc jsonschema: validate array keywords
Add validation for the keywords dealing with JSON arrays.

We call the elements of an array its "items."

The unevaluatedItems keyword introduces some complexity. Its schema
applies to all items in the array that have not been successfully
validated ("evaluated" is the spec's misleading term) by this schema or
subschemas acting on the same array. The logic keywords like allOf and
anyOf thus contribute to the set of evaluated items.

Following the spec, we say that a schema produces "annotations" that
describe the items it has evaluated. The annotations type collects this
information. For the "contains" keyword we need to represent the set
of evaluated items, but for others we can optimize with an integer or
boolean. For example, the "items" keyword applies its schema to every
item in the array. If even one fails to validate, the array fails to
validate, and the validate call exits before reaching unevaluatedItems.
Therefore, if "items" succeeds, it has successfully validated every
item, so unevaluatedItems does not apply. A boolean annotation suffices
to record this fact.

The logic of "anyOf" must change so it can track all evaluated items.
It must still visit the remaining subschemas even after a subschema
succeeds.

Anticipating the next CL, which deals with JSON objects (maps), the
annotations struct supports properties as well as items.

Change-Id: I98283d36c9a55f4cae97636cbec20c4886daea11
Reviewed-on: https://go-review.googlesource.com/c/tools/+/668235
Reviewed-by: Alan Donovan <adonovan@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
2025-04-30 13:06:13 -07:00
Jonathan Amsterdam
9396e7f6a6 jsonschema: validate logic keywords
Validate keywords that combine schemas with various logical operators.

Also add iterators over schemas. Now we only need them to skip some
tests, but later they will come in handy for non-test code.

Change-Id: Idaf41efea4d693b6be0ee5c6c3a527664b8c472f
Reviewed-on: https://go-review.googlesource.com/c/tools/+/668115
Reviewed-by: Alan Donovan <adonovan@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
2025-04-30 12:16:32 -07:00
Jonathan Amsterdam
061f842459 jsonschema: validate numbers and strings
Add validation for keywords related to numbers and strings.

It may be surprising that keywords like "minimum" or "minLength"
don't imply that the instance is a number or string.
But that is how JSON Schema is designed.

Change-Id: I8805a5fe91ee345931e1c989f174ea2d0be6665a
Reviewed-on: https://go-review.googlesource.com/c/tools/+/667975
Reviewed-by: Robert Findley <rfindley@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Jonathan Amsterdam <jba@google.com>
2025-04-30 09:35:26 -07:00
Rob Findley
3b86fb5601 internal/mcp: export the Transport interface; add a Server example
Export the Transport interface, as there's no reason users shouldn't be
able to define their own transports: they are just bidirectional
streams.

Also, add a godoc example for basic Server usage.

Finally, remove some TODOs that existed due to a bad merge: they are
related to the (as yet unsubmitted) streamable HTTP transport.

Change-Id: Id669793fc80630e667d50611fe2876d09125a025
Reviewed-on: https://go-review.googlesource.com/c/tools/+/668675
TryBot-Bypass: Robert Findley <rfindley@google.com>
Reviewed-by: Sam Thanawalla <samthanawalla@google.com>
Auto-Submit: Robert Findley <rfindley@google.com>
2025-04-28 13:38:53 -07:00
Hongxiang Jiang
fd3ce0d810 internal/mcp: dynamically determine the mcp server based on URL
Based on my understanding, the getServer function is used to determine
which MCP server should be serving the session.

User might want to dynamically determine which MCP server to serve when
a new request comes in. In mcp/examples, two MCP servers are created
serving at the same port but under different URL "/greeter1",
"/greeter2". The MCP client will reach out to different URLs for
different MCP servers.

As a TODO, if the getServer() returns nil, the program will crash when
handing MCP request.

Change-Id: I4431266666e9ea28118e827a94eb1359b1fb3a81
Reviewed-on: https://go-review.googlesource.com/c/tools/+/668535
Reviewed-by: Robert Findley <rfindley@google.com>
Auto-Submit: Hongxiang Jiang <hxjiang@golang.org>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
2025-04-28 12:16:50 -07:00
Rob Findley
7a7d49dc2a internal/mcp: clean up SSE server shutdown.
Add a bit more theory around SSE transport shutdown, and some
documentation of the SSE transport protocol itself. Additionally, remove
a TODO to avoid the use of channel buffering for message queues in http
transports; instead, always write to message buffers in a select
statement containing a read from the done channel. The bounded size of
message buffers then serves to create backpressure for an overloaded
server.

Change-Id: I5701c5b95a5ae73d796a634e434f41dfcdbddf51
Reviewed-on: https://go-review.googlesource.com/c/tools/+/668237
Reviewed-by: Jonathan Amsterdam <jba@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Robert Findley <rfindley@google.com>
2025-04-28 09:44:29 -07:00
Jonathan Amsterdam
c99ff4897b jsonschema: validate some keywords
This CL implements validation for the "type", "enum" and "const"
keywords.

Validation in its full generality requires that references in the schema
be resolved. We put that off for now; it isn't needed for most simple
keywords.

The JSON Schema folks provide an extensive test suite for validation at
https://github.com/json-schema-org/JSON-Schema-Test-Suite. We use it for
our tests, copying the necessary files into testdata. The files aren't
perfectly independent; for example, one test in enum.json requires the
"properties" keyword, which we haven't done yet. We will excise those
tests via calls to t.Skip as they arise.

Change-Id: I568b5c87802a39aecbc58f342931308fc8fb211c
Reviewed-on: https://go-review.googlesource.com/c/tools/+/667875
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Alan Donovan <adonovan@google.com>
2025-04-25 08:34:02 -07:00
Jonathan Amsterdam
3434e57007 internal/mcp/internal/jsonschema: schema definition
The first of several CLs providing JSON Schema validation.

Replace the existing Schema type with one that has all the keywords
of the most current version of the JSON Schema spec, called 2020-12.

The 2020-12 spec can be represented type-safely in Go with one exception:
the "type" keyword can be either a string or a []string. To handle this
safely, both Type and Types fields are defined. Custom
JSONMarshal/Unmarshal methods handle the conversion. We need the
unmarshal anyway because "true" and "false" are valid schemas.

Unfortunately, the MCP spec uses the older "draft7" version of JSON
Schema, but the two are close enough for code generation to work.
I confirmed that the protocol generator produces the identical output.

Change-Id: I44f6ea2f3a3f8498979946f69dfb7f50afa1acad
Reviewed-on: https://go-review.googlesource.com/c/tools/+/667855
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Alan Donovan <adonovan@google.com>
2025-04-25 08:33:53 -07:00