Skip to content

Commit 7ee1650

Browse files
hashrocketeervnegrisoloGabriel Reis
committed
Fix MCP multi user server
Co-authored-by: Vinicius Negrisolo <vinicius.negrisolo@hashrocket.com> Co-authored-by: Gabriel Reis <gabriel.reis@hashrocket.com>
1 parent 839e8dd commit 7ee1650

File tree

4 files changed

+35
-94
lines changed

4 files changed

+35
-94
lines changed

lib/tilex/mcp/new_post.ex

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,14 @@ defmodule Tilex.MCP.NewPost do
99

1010
import Ecto.Query, only: [from: 2]
1111

12-
alias Ecto.Changeset
1312
alias Anubis.Server.Response
13+
alias Ecto.Changeset
1414
alias Tilex.Blog.Channel
1515
alias Tilex.Blog.Developer
16+
alias Tilex.Blog.Developer
1617
alias Tilex.Blog.Post
1718
alias Tilex.Repo
19+
alias Tilex.Repo
1820
alias TilexWeb.Endpoint
1921
alias TilexWeb.Router.Helpers, as: Routes
2022

@@ -57,7 +59,16 @@ defmodule Tilex.MCP.NewPost do
5759
end
5860

5961
defp get_current_user(frame) do
60-
case Map.get(frame.assigns, :current_user) do
62+
headers = Enum.into(frame.transport.req_headers, %{})
63+
signed_token = headers["x-api-key"]
64+
65+
with "" <> _ <- signed_token,
66+
{:ok, mcp_api_key} <- Developer.verify_mcp_api_key(TilexWeb.Endpoint, signed_token) do
67+
Repo.one(from d in Developer, where: d.mcp_api_key == ^mcp_api_key)
68+
else
69+
_ -> nil
70+
end
71+
|> case do
6172
nil -> {:error, "User is not authenticated to create TILs"}
6273
%Developer{} = user -> {:ok, user}
6374
end

lib/tilex/mcp/server.ex

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,6 @@
11
defmodule Tilex.MCP.Server do
22
use Anubis.Server, name: "TIL", version: "1.0.0", capabilities: [:resources, :tools]
33

4-
import Ecto.Query, only: [from: 2]
5-
6-
alias Tilex.Repo
7-
alias Tilex.Blog.Developer
8-
94
component(Tilex.MCP.ListChannels)
105
component(Tilex.MCP.NewPost)
11-
12-
@impl true
13-
def init(_arg, frame) do
14-
headers = Enum.into(frame.transport.req_headers, %{})
15-
user = get_current_user(headers["x-api-key"])
16-
assigns = Map.put(frame.assigns || %{}, :current_user, user)
17-
frame = Map.put(frame, :assigns, assigns)
18-
{:ok, frame}
19-
end
20-
21-
defp get_current_user(signed_token) do
22-
with "" <> _ <- signed_token,
23-
{:ok, mcp_api_key} <- Developer.verify_mcp_api_key(TilexWeb.Endpoint, signed_token) do
24-
Repo.one(from d in Developer, where: d.mcp_api_key == ^mcp_api_key)
25-
else
26-
_ -> nil
27-
end
28-
end
296
end

test/tilex/mcp/new_post_test.exs

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,28 @@ defmodule Tilex.MCP.NewPostTest do
22
use Tilex.DataCase, async: false
33

44
alias Anubis.Server.Response
5+
alias Tilex.Blog.Developer
56
alias Tilex.Blog.Post
67
alias Tilex.Factory
78
alias Tilex.MCP.NewPost
89
alias Tilex.Repo
910

1011
describe "execute/2" do
11-
test "creates post successfully with valid data and authenticated user" do
12-
developer = Factory.insert!(:developer)
12+
setup do
13+
%{
14+
mcp_api_key: mcp_api_key,
15+
signed_token: signed_token
16+
} = Developer.generate_mcp_api_key(TilexWeb.Endpoint)
17+
18+
developer = Factory.insert!(:developer, mcp_api_key: mcp_api_key)
19+
20+
[developer: developer, signed_token: signed_token]
21+
end
22+
23+
test "creates post successfully with valid data and authenticated user", %{
24+
developer: developer,
25+
signed_token: signed_token
26+
} do
1327
channel = Factory.insert!(:channel, name: "elixir")
1428

1529
title = "My First TIL"
@@ -23,7 +37,7 @@ defmodule Tilex.MCP.NewPostTest do
2337
body: body
2438
}
2539

26-
frame = %{assigns: %{current_user: developer}}
40+
frame = %{transport: %{req_headers: %{"x-api-key" => signed_token}}}
2741

2842
assert {:reply, response, returned_frame} = NewPost.execute(input, frame)
2943

@@ -64,7 +78,7 @@ defmodule Tilex.MCP.NewPostTest do
6478
body: body
6579
}
6680

67-
frame = %{assigns: %{}}
81+
frame = %{transport: %{req_headers: %{}}}
6882

6983
assert {:reply, response, returned_frame} = NewPost.execute(input, frame)
7084

@@ -82,9 +96,7 @@ defmodule Tilex.MCP.NewPostTest do
8296
} = response
8397
end
8498

85-
test "raises error when channel does not exist" do
86-
developer = Factory.insert!(:developer)
87-
99+
test "raises error when channel does not exist", %{signed_token: signed_token} do
88100
title = "My First TIL"
89101
body = "Today I learned something amazing about Elixir."
90102

@@ -94,7 +106,7 @@ defmodule Tilex.MCP.NewPostTest do
94106
body: body
95107
}
96108

97-
frame = %{assigns: %{current_user: developer}}
109+
frame = %{transport: %{req_headers: %{"x-api-key" => signed_token}}}
98110

99111
assert {:reply, response, returned_frame} = NewPost.execute(input, frame)
100112

@@ -112,8 +124,7 @@ defmodule Tilex.MCP.NewPostTest do
112124
} = response
113125
end
114126

115-
test "returns validation error" do
116-
developer = Factory.insert!(:developer)
127+
test "returns validation error", %{signed_token: signed_token} do
117128
channel = Factory.insert!(:channel, name: "elixir")
118129

119130
title = String.duplicate("a", 51)
@@ -125,7 +136,7 @@ defmodule Tilex.MCP.NewPostTest do
125136
body: body
126137
}
127138

128-
frame = %{assigns: %{current_user: developer}}
139+
frame = %{transport: %{req_headers: %{"x-api-key" => signed_token}}}
129140

130141
assert {:reply, response, returned_frame} = NewPost.execute(input, frame)
131142

test/tilex/mcp/server_test.exs

Lines changed: 0 additions & 58 deletions
This file was deleted.

0 commit comments

Comments
 (0)