Skip to content

Safer sse #87

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 12 commits into
base: main
Choose a base branch
from
Open
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
30 changes: 15 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,16 @@
<br/>
<div align="center">

![GitHub stars](https://img.shields.io/github/stars/metoro-io/mcp-golang?style=social)
![GitHub forks](https://img.shields.io/github/forks/metoro-io/mcp-golang?style=social)
![GitHub issues](https://img.shields.io/github/issues/metoro-io/mcp-golang)
![GitHub pull requests](https://img.shields.io/github/issues-pr/metoro-io/mcp-golang)
![GitHub license](https://img.shields.io/github/license/metoro-io/mcp-golang)
![GitHub contributors](https://img.shields.io/github/contributors/metoro-io/mcp-golang)
![GitHub last commit](https://img.shields.io/github/last-commit/metoro-io/mcp-golang)
[![GoDoc](https://pkg.go.dev/badge/github.com/metoro-io/mcp-golang.svg)](https://pkg.go.dev/github.com/metoro-io/mcp-golang)
[![Go Report Card](https://goreportcard.com/badge/github.com/metoro-io/mcp-golang)](https://goreportcard.com/report/github.com/metoro-io/mcp-golang)
![Tests](https://github.com/metoro-io/mcp-golang/actions/workflows/go-test.yml/badge.svg)
![GitHub stars](https://img.shields.io/github/stars/rvoh-emccaleb/mcp-golang?style=social)
![GitHub forks](https://img.shields.io/github/forks/rvoh-emccaleb/mcp-golang?style=social)
![GitHub issues](https://img.shields.io/github/issues/rvoh-emccaleb/mcp-golang)
![GitHub pull requests](https://img.shields.io/github/issues-pr/rvoh-emccaleb/mcp-golang)
![GitHub license](https://img.shields.io/github/license/rvoh-emccaleb/mcp-golang)
![GitHub contributors](https://img.shields.io/github/contributors/rvoh-emccaleb/mcp-golang)
![GitHub last commit](https://img.shields.io/github/last-commit/rvoh-emccaleb/mcp-golang)
[![GoDoc](https://pkg.go.dev/badge/github.com/rvoh-emccaleb/mcp-golang.svg)](https://pkg.go.dev/github.com/rvoh-emccaleb/mcp-golang)
[![Go Report Card](https://goreportcard.com/badge/github.com/rvoh-emccaleb/mcp-golang)](https://goreportcard.com/report/github.com/rvoh-emccaleb/mcp-golang)
![Tests](https://github.com/rvoh-emccaleb/mcp-golang/actions/workflows/go-test.yml/badge.svg)



Expand All @@ -37,7 +37,7 @@ Docs at [https://mcpgolang.com](https://mcpgolang.com)

## Example Usage

Install with `go get github.com/metoro-io/mcp-golang`
Install with `go get github.com/rvoh-emccaleb/mcp-golang`

### Server Example

Expand All @@ -46,8 +46,8 @@ package main

import (
"fmt"
"github.com/metoro-io/mcp-golang"
"github.com/metoro-io/mcp-golang/transport/stdio"
"github.com/rvoh-emccaleb/mcp-golang"
"github.com/rvoh-emccaleb/mcp-golang/transport/stdio"
)

// Tool arguments are just structs, annotated with jsonschema tags
Expand Down Expand Up @@ -121,8 +121,8 @@ package main
import (
"context"
"log"
mcp "github.com/metoro-io/mcp-golang"
"github.com/metoro-io/mcp-golang/transport/stdio"
mcp "github.com/rvoh-emccaleb/mcp-golang"
"github.com/rvoh-emccaleb/mcp-golang/transport/stdio"
)

// Define type-safe arguments
Expand Down
48 changes: 37 additions & 11 deletions client.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import (
"context"
"encoding/json"

"github.com/metoro-io/mcp-golang/internal/protocol"
"github.com/metoro-io/mcp-golang/transport"
"github.com/pkg/errors"
"github.com/rvoh-emccaleb/mcp-golang/internal/protocol"
"github.com/rvoh-emccaleb/mcp-golang/transport"
)

// Client represents an MCP client that can connect to and interact with MCP servers
Expand All @@ -25,8 +25,21 @@ func NewClient(transport transport.Transport) *Client {
}
}

// A bit loosey goosey, but it works for now.
// See: https://spec.modelcontextprotocol.io/specification/2024-11-05/basic/lifecycle/
type InitializeRequestParams struct {
ProtocolVersion string `json:"protocolVersion"`
ClientInfo InitializeRequestClientInfo `json:"clientInfo"`
Capabilities map[string]interface{} `json:"capabilities"`
}

type InitializeRequestClientInfo struct {
Name string `json:"name"`
Version string `json:"version"`
}

// Initialize connects to the server and retrieves its capabilities
func (c *Client) Initialize(ctx context.Context) (*InitializeResponse, error) {
func (c *Client) Initialize(ctx context.Context, params *InitializeRequestParams) (*InitializeResponse, error) {
if c.initialized {
return nil, errors.New("client already initialized")
}
Expand All @@ -36,8 +49,8 @@ func (c *Client) Initialize(ctx context.Context) (*InitializeResponse, error) {
return nil, errors.Wrap(err, "failed to connect transport")
}

// Make initialize request to server
response, err := c.protocol.Request(ctx, "initialize", map[string]interface{}{}, nil)
// Begin initialization handshake with server
response, err := c.protocol.Request(ctx, "initialize", params, nil)
if err != nil {
return nil, errors.Wrap(err, "failed to initialize")
}
Expand All @@ -53,8 +66,15 @@ func (c *Client) Initialize(ctx context.Context) (*InitializeResponse, error) {
return nil, errors.Wrap(err, "failed to unmarshal initialize response")
}

// Finish initialization handshake with server
err = c.protocol.Notification("notifications/initialized", map[string]interface{}{})
if err != nil {
return nil, errors.Wrap(err, "failed to send initialized notification")
}

c.capabilities = &initResult.Capabilities
c.initialized = true

return &initResult, nil
}

Expand Down Expand Up @@ -235,17 +255,13 @@ func (c *Client) ReadResource(ctx context.Context, uri string) (*ResourceRespons
return nil, errors.New("invalid response type")
}

var resourceResponse resourceResponseSent
var resourceResponse ResourceResponse
err = json.Unmarshal(responseBytes, &resourceResponse)
if err != nil {
return nil, errors.Wrap(err, "failed to unmarshal resource response")
}

if resourceResponse.Error != nil {
return nil, resourceResponse.Error
}

return resourceResponse.Response, nil
return &resourceResponse, nil
}

// Ping sends a ping request to the server to check connectivity
Expand All @@ -266,3 +282,13 @@ func (c *Client) Ping(ctx context.Context) error {
func (c *Client) GetCapabilities() *ServerCapabilities {
return c.capabilities
}

// Close cleans up resources used by the client, including the protocol and transport layers.
// It should be called when the client is no longer needed.
func (c *Client) Close() error {
if err := c.protocol.Close(); err != nil {
return errors.Wrap(err, "failed to close protocol")
}

return nil
}
41 changes: 39 additions & 2 deletions content_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,14 +85,51 @@ type EmbeddedResource struct {

// Custom JSON marshaling for EmbeddedResource
func (c EmbeddedResource) MarshalJSON() ([]byte, error) {
type wrapper struct {
Type string `json:"embeddedResourceType"`
*TextResourceContents
*BlobResourceContents
}

w := wrapper{Type: string(c.EmbeddedResourceType)}

switch c.EmbeddedResourceType {
case embeddedResourceTypeBlob:
return json.Marshal(c.BlobResourceContents)
w.BlobResourceContents = c.BlobResourceContents
case embeddedResourceTypeText:
return json.Marshal(c.TextResourceContents)
w.TextResourceContents = c.TextResourceContents
default:
return nil, fmt.Errorf("unknown embedded resource type: %s", c.EmbeddedResourceType)
}

return json.Marshal(w)
}

func (c *EmbeddedResource) UnmarshalJSON(data []byte) error {
var wrapper struct {
Type string `json:"embeddedResourceType"`
Raw json.RawMessage `json:"-"`
}

wrapper.Raw = data
if err := json.Unmarshal(data, &wrapper); err != nil {
return err
}

c.EmbeddedResourceType = embeddedResourceType(wrapper.Type)

switch c.EmbeddedResourceType {
case embeddedResourceTypeText:
c.TextResourceContents = new(TextResourceContents)
return json.Unmarshal(wrapper.Raw, c.TextResourceContents)

case embeddedResourceTypeBlob:
c.BlobResourceContents = new(BlobResourceContents)
return json.Unmarshal(wrapper.Raw, c.BlobResourceContents)

default:
return fmt.Errorf("unknown embedded resource type: %s", wrapper.Type)
}
}

type ContentType string
Expand Down
4 changes: 2 additions & 2 deletions docs/change-notifications.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ package main

import (
"fmt"
mcp_golang "github.com/metoro-io/mcp-golang"
"github.com/metoro-io/mcp-golang/transport/stdio"
mcp_golang "github.com/rvoh-emccaleb/mcp-golang"
"github.com/rvoh-emccaleb/mcp-golang/transport/stdio"
"time"
)

Expand Down
8 changes: 4 additions & 4 deletions docs/client.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ The MCP client provides a simple and intuitive way to interact with MCP servers.
Add the MCP Golang package to your project:

```bash
go get github.com/metoro-io/mcp-golang
go get github.com/rvoh-emccaleb/mcp-golang
```

## Basic Usage
Expand All @@ -21,8 +21,8 @@ Here's a simple example of creating and initializing an MCP client:

```go
import (
mcp "github.com/metoro-io/mcp-golang"
"github.com/metoro-io/mcp-golang/transport/stdio"
mcp "github.com/rvoh-emccaleb/mcp-golang"
"github.com/rvoh-emccaleb/mcp-golang/transport/stdio"
)

// Create a transport (stdio in this example)
Expand Down Expand Up @@ -197,7 +197,7 @@ if err != nil {

## Complete Example

For a complete working example, check out our [example client implementation](https://github.com/metoro-io/mcp-golang/tree/main/examples/client).
For a complete working example, check out our [example client implementation](https://github.com/rvoh-emccaleb/mcp-golang/tree/main/examples/client).

## Transport Options

Expand Down
4 changes: 2 additions & 2 deletions docs/contributing.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ To set up your development environment, follow these steps:

1. Clone the repository:
```bash
git clone https://github.com/metoro-io/mcp-golang.git
git clone https://github.com/rvoh-emccaleb/mcp-golang.git
cd mcp-golang
```

Expand Down Expand Up @@ -210,6 +210,6 @@ When your PR merges into the main branch, it will be deployed automatically.

## Getting Help

- Check existing [GitHub issues](https://github.com/metoro-io/mcp-golang/issues)
- Check existing [GitHub issues](https://github.com/rvoh-emccaleb/mcp-golang/issues)
- Join our [Discord community](https://discord.gg/33saRwE3pT)
- Read the [Model Context Protocol specification](https://modelcontextprotocol.io/)
6 changes: 3 additions & 3 deletions docs/mint.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,13 @@
},
"topbarCtaButton": {
"name": "Github Repo",
"url": "https://github.com/metoro-io/mcp-golang"
"url": "https://github.com/rvoh-emccaleb/mcp-golang"
},
"anchors": [
{
"name": "Github",
"icon": "github",
"url": "https://github.com/metoro-io/mcp-golang"
"url": "https://github.com/rvoh-emccaleb/mcp-golang"
},
{
"name": "Discord Community",
Expand Down Expand Up @@ -62,7 +62,7 @@
],
"footerSocials": {
"x": "https://x.com/metoro_ai",
"github": "https://github.com/metoro-io/mcp-golang",
"github": "https://github.com/rvoh-emccaleb/mcp-golang",
"website": "https://https://metoro.io/"
}
}
20 changes: 10 additions & 10 deletions docs/quickstart.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ description: 'Set up your first mcp-golang server'
First, add mcp-golang to your project:

```bash
go get github.com/metoro-io/mcp-golang
go get github.com/rvoh-emccaleb/mcp-golang
```

## Basic Usage
Expand All @@ -20,8 +20,8 @@ package main

import (
"fmt"
"github.com/metoro-io/mcp-golang"
"github.com/metoro-io/mcp-golang/transport/stdio"
"github.com/rvoh-emccaleb/mcp-golang"
"github.com/rvoh-emccaleb/mcp-golang/transport/stdio"
)

type Content struct {
Expand Down Expand Up @@ -93,8 +93,8 @@ package main
import (
"context"
"log"
"github.com/metoro-io/mcp-golang"
"github.com/metoro-io/mcp-golang/transport/http"
"github.com/rvoh-emccaleb/mcp-golang"
"github.com/rvoh-emccaleb/mcp-golang/transport/http"
)

func main() {
Expand Down Expand Up @@ -122,8 +122,8 @@ package main

import (
"github.com/gin-gonic/gin"
"github.com/metoro-io/mcp-golang"
"github.com/metoro-io/mcp-golang/transport/http"
"github.com/rvoh-emccaleb/mcp-golang"
"github.com/rvoh-emccaleb/mcp-golang/transport/http"
)

func main() {
Expand Down Expand Up @@ -155,8 +155,8 @@ package main
import (
"context"
"log"
"github.com/metoro-io/mcp-golang"
"github.com/metoro-io/mcp-golang/transport/http"
"github.com/rvoh-emccaleb/mcp-golang"
"github.com/rvoh-emccaleb/mcp-golang/transport/http"
)

func main() {
Expand All @@ -183,4 +183,4 @@ func main() {

- If you're interested in contributing to mcp-golang, check out [Development Guide](/development) for more detailed information
- Join our [Discord Community](https://discord.gg/33saRwE3pT) for support
- Visit our [GitHub Repository](https://github.com/metoro-io/mcp-golang) to contribute
- Visit our [GitHub Repository](https://github.com/rvoh-emccaleb/mcp-golang) to contribute
4 changes: 2 additions & 2 deletions docs/tools.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ package main

import (
"fmt"
"github.com/metoro-io/mcp-golang"
"github.com/metoro-io/mcp-golang/transport/stdio"
"github.com/rvoh-emccaleb/mcp-golang"
"github.com/rvoh-emccaleb/mcp-golang/transport/stdio"
)

type HelloArguments struct {
Expand Down
4 changes: 2 additions & 2 deletions examples/basic_tool_server/basic_tool_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ package main

import (
"fmt"
"github.com/metoro-io/mcp-golang"
"github.com/metoro-io/mcp-golang/transport/stdio"
"github.com/rvoh-emccaleb/mcp-golang"
"github.com/rvoh-emccaleb/mcp-golang/transport/stdio"
)

type Content struct {
Expand Down
Loading