ask-anychat-mcp 0.1.1

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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: e4c8dd1fbdd06af3eea37bc761e1181b0b1fd6b8a4b9a192d87cbdce9ec76bd6
4
+ data.tar.gz: a028698b40e423aa5494609fae8674f6a0cc986d6d07c16f0771f653022b5bb6
5
+ SHA512:
6
+ metadata.gz: 6bc18d87d53dbe770e28801ed7ea9e497adc8aa7181147255a64ed824114a12abd3d3ea27efaba1c26ae1a2d4d9171dbfc16f02890f8ba5d5893d317463afe6b
7
+ data.tar.gz: ab7a9c27147b4688673098b9def67d76bd5085b51c8139e81bc9c26f414382a0fbf47520075aa353d34ab76d92c77dc5c56df2175179db9d28dff6199910205c
data/CHANGELOG.md ADDED
@@ -0,0 +1,26 @@
1
+ ## [0.1.0] - 2026-09-17
2
+
3
+ ### Added
4
+
5
+ - **An MCP server for Anychat**, served over stdio —
6
+ `Ask::AnyChat::MCP.start` and the `ask-anychat-mcp` executable. Tool names are
7
+ prefixed `ask_anychat_` so they cannot collide with a client's own tools of the
8
+ same name, as the other ask MCP servers are.
9
+
10
+ - **Five tools, one per operation** — `ask_anychat_list_agents`,
11
+ `ask_anychat_get_agent`, `ask_anychat_create_agent`,
12
+ `ask_anychat_update_agent` and `ask_anychat_delete_agent`. Every one names a
13
+ workspace, because a workspace is what a token reaches.
14
+
15
+ - **Arguments checked before the call** — a missing or misspelled argument is
16
+ named, with the ones that were on offer, rather than being dropped and
17
+ surfacing later as an unexplained result. The schema each tool declares is
18
+ also enforced at the protocol boundary.
19
+
20
+ - **Refusals come back as text** — the sentence the API wrote, prefixed with
21
+ `Error:`, so a model can act on it instead of being handed an exception that
22
+ ends the conversation.
23
+
24
+ - **`Ask::AnyChat::MCP.tools(client:)`** — the client can be supplied, which is
25
+ how a host points the server at a particular deployment and how the tests hold
26
+ the API still.
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Kaka Ruto
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,74 @@
1
+ # Ask::AnyChat::MCP
2
+
3
+ MCP server for [Anychat](https://anywaye.com), for the
4
+ [ask-rb](https://github.com/ask-rb) ecosystem.
5
+
6
+ Exposes the agents a workspace owns as callable tools over stdio, so a client
7
+ that speaks the Model Context Protocol can create and manage them without
8
+ knowing anything about the API underneath. The tool shell lives here; the API
9
+ client is [ask-anychat](https://github.com/ask-rb/ask-anychat).
10
+
11
+ ## Installation
12
+
13
+ ```ruby
14
+ gem "ask-anychat-mcp"
15
+ ```
16
+
17
+ ## Usage
18
+
19
+ Register the executable with an MCP client:
20
+
21
+ ```json
22
+ {
23
+ "mcp": {
24
+ "servers": {
25
+ "ask-anychat-mcp": {
26
+ "type": "stdio",
27
+ "command": "ask-anychat-mcp",
28
+ "env": { "ANYCHAT_TOKEN": "..." }
29
+ }
30
+ }
31
+ }
32
+ }
33
+ ```
34
+
35
+ Set `ANYCHAT_BASE_URL` too when pointing at a deployment that is not the hosted
36
+ app. Mint a token in Anychat under Settings → API tokens.
37
+
38
+ ### Tools
39
+
40
+ | Tool | What it does |
41
+ | --- | --- |
42
+ | `ask_anychat_list_agents` | Every agent a workspace owns, with the address each answers on |
43
+ | `ask_anychat_get_agent` | One agent, by the address it answers on |
44
+ | `ask_anychat_create_agent` | Bring a new agent into being — a name is all it takes |
45
+ | `ask_anychat_update_agent` | Change one; only the arguments you pass are written |
46
+ | `ask_anychat_delete_agent` | Retire one; its address becomes free |
47
+
48
+ Every tool names a workspace, because a workspace is what a token reaches.
49
+
50
+ Names are prefixed `ask_anychat_` to keep them from colliding with a client's own
51
+ tools of the same name, as the other ask MCP servers are.
52
+
53
+ ### What comes back
54
+
55
+ A refusal is text the model can act on rather than an exception that ends the
56
+ conversation, and it carries the sentence the API wrote:
57
+
58
+ ```
59
+ Error: No agent at /anywaye/nope.
60
+ ```
61
+
62
+ The same is true of an argument that was missing or misspelled — a model that
63
+ typed `name` where `display_name` was wanted is told so, rather than having the
64
+ value quietly dropped.
65
+
66
+ ## Contributing
67
+
68
+ Run `bin/setup` once, then `bundle exec rake test`. Until `ask-anychat` and
69
+ `ask-mcp` are released, the Gemfile consumes both from the working copies
70
+ alongside this one.
71
+
72
+ ## License
73
+
74
+ MIT.
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "ask/anychat/mcp"
5
+
6
+ Ask::AnyChat::MCP.start
@@ -0,0 +1,105 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ask
4
+ module AnyChat
5
+ module MCP
6
+ # The duck type the MCP adapter expects: a name, a description, a JSON
7
+ # Schema, and a call.
8
+ #
9
+ # Arguments are checked here rather than at the API, so a model that
10
+ # misspells a parameter is told which one it typed and which were on
11
+ # offer — instead of being handed a status code it cannot read. Failures
12
+ # come back as text for the same reason: this is a conversation.
13
+ class Tool
14
+ class << self
15
+ # Not `name`: that is already how a class answers to itself, and
16
+ # taking it over breaks more than it tells.
17
+ def tool_name(value = nil)
18
+ @tool_name = value if value
19
+ @tool_name
20
+ end
21
+
22
+ def description(text = nil)
23
+ @description = text if text
24
+ @description
25
+ end
26
+
27
+ def params(schema = nil)
28
+ @params = schema if schema
29
+ @params || {}
30
+ end
31
+ end
32
+
33
+ def initialize(client: nil)
34
+ @client = client
35
+ end
36
+
37
+ def name
38
+ self.class.tool_name
39
+ end
40
+
41
+ def description
42
+ self.class.description
43
+ end
44
+
45
+ def params_schema
46
+ self.class.params
47
+ end
48
+
49
+ def call(arguments = {})
50
+ args = stringify(arguments)
51
+ violation = violation(args)
52
+ return violation if violation
53
+
54
+ run(args)
55
+ rescue AnyChat::Error => e
56
+ "Error: #{e.message}"
57
+ end
58
+
59
+ private
60
+
61
+ attr_reader :client
62
+
63
+ # Built once per call and only if a tool needs it, so the server can be
64
+ # started without a token in the environment.
65
+ def anychat
66
+ @anychat ||= client || AnyChat.client
67
+ end
68
+
69
+ def run(_args)
70
+ raise NotImplementedError, "#{self.class} must implement #run"
71
+ end
72
+
73
+ def stringify(arguments)
74
+ arguments.each_with_object({}) { |(key, value), out| out[key.to_s] = value }
75
+ end
76
+
77
+ # Unknown and missing arguments are named, not ignored: a model that
78
+ # typed `name` where `display_name` was wanted should hear about it.
79
+ def violation(args)
80
+ allowed = params_schema[:properties].to_h.keys.map(&:to_s)
81
+ required = Array(params_schema[:required]).map(&:to_s)
82
+
83
+ missing = required - args.keys
84
+ if missing.any?
85
+ return "Error: missing required argument(s): #{missing.join(', ')}. Expected: #{allowed.join(', ')}"
86
+ end
87
+
88
+ extra = args.keys - allowed
89
+ return "Error: unknown argument(s): #{extra.join(', ')}. Expected: #{allowed.join(', ')}" if extra.any?
90
+
91
+ nil
92
+ end
93
+
94
+ # Only what the caller actually sent: an omitted optional argument is an
95
+ # omission, not a nil to write over what is already there.
96
+ def writable(args, *names)
97
+ names.each_with_object({}) do |name, out|
98
+ key = name.to_s
99
+ out[name.to_sym] = args[key] if args.key?(key)
100
+ end
101
+ end
102
+ end
103
+ end
104
+ end
105
+ end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ask
4
+ module AnyChat
5
+ module MCP
6
+ module Tools
7
+ # A new agent for a workspace.
8
+ class CreateAgent < Tool
9
+ tool_name "ask_anychat_create_agent"
10
+ description "Bring a new agent into being in a workspace. Only a name is needed; " \
11
+ "the address it answers on is derived from that name, and a taken one " \
12
+ "is handed the first free variant rather than failing. Pass handle to " \
13
+ "choose the address yourself."
14
+ params(
15
+ type: "object",
16
+ properties: {
17
+ workspace: {
18
+ type: "string",
19
+ description: "The workspace's username, the first half of /<workspace>/<agent>"
20
+ },
21
+ display_name: {
22
+ type: "string",
23
+ description: "What the agent is called, e.g. \"Support\""
24
+ },
25
+ handle: {
26
+ type: "string",
27
+ description: "The address to answer on. Defaults to one derived from the name."
28
+ },
29
+ description: {
30
+ type: "string",
31
+ description: "One line about what this agent is for."
32
+ },
33
+ public: {
34
+ type: "boolean",
35
+ description: "Whether the world can find it. Defaults to true."
36
+ }
37
+ },
38
+ required: %w[workspace display_name]
39
+ )
40
+
41
+ private
42
+
43
+ def run(args)
44
+ agent = anychat.create_workspace_agent(
45
+ args["workspace"],
46
+ **writable(args, :display_name, :handle, :description, :public)
47
+ )
48
+
49
+ "Created #{agent['display_name']} at #{agent['address']}."
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ask
4
+ module AnyChat
5
+ module MCP
6
+ module Tools
7
+ # An agent leaves the workspace, and its address becomes free.
8
+ #
9
+ # Conversations customers had with it are kept, so a retired agent still
10
+ # appears in that history — which is worth saying, because an owner who
11
+ # expects the record gone would be wrong to.
12
+ class DeleteAgent < Tool
13
+ tool_name "ask_anychat_delete_agent"
14
+ description "Retire an agent from a workspace. Its address becomes free for another " \
15
+ "agent to take. Conversations it already had are kept."
16
+ params(
17
+ type: "object",
18
+ properties: {
19
+ workspace: {
20
+ type: "string",
21
+ description: "The workspace's username, the first half of /<workspace>/<agent>"
22
+ },
23
+ agent: {
24
+ type: "string",
25
+ description: "The address it answers on, the second half of /<workspace>/<agent>"
26
+ }
27
+ },
28
+ required: %w[workspace agent]
29
+ )
30
+
31
+ private
32
+
33
+ def run(args)
34
+ anychat.destroy_workspace_agent(args["workspace"], args["agent"])
35
+
36
+ "Retired the agent at /#{args['workspace']}/#{args['agent']}. The address is free again."
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ask
4
+ module AnyChat
5
+ module MCP
6
+ module Tools
7
+ # One agent, by the address it answers on.
8
+ class GetAgent < Tool
9
+ tool_name "ask_anychat_get_agent"
10
+ description "Read one agent of a workspace, by the address it answers on. Use " \
11
+ "ask_anychat_list_agents first if you do not know the address."
12
+ params(
13
+ type: "object",
14
+ properties: {
15
+ workspace: {
16
+ type: "string",
17
+ description: "The workspace's username, the first half of /<workspace>/<agent>"
18
+ },
19
+ agent: {
20
+ type: "string",
21
+ description: "The address it answers on, the second half of /<workspace>/<agent>"
22
+ }
23
+ },
24
+ required: %w[workspace agent]
25
+ )
26
+
27
+ private
28
+
29
+ def run(args)
30
+ agent = anychat.workspace_agent(args["workspace"], args["agent"])
31
+
32
+ [
33
+ "#{agent['display_name']} at #{agent['address']}",
34
+ agent["description"].to_s.strip.empty? ? nil : agent["description"],
35
+ agent["public"] ? "Public" : "Private"
36
+ ].compact.join("\n")
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ask
4
+ module AnyChat
5
+ module MCP
6
+ module Tools
7
+ # The agents a workspace owns, oldest first.
8
+ class ListAgents < Tool
9
+ tool_name "ask_anychat_list_agents"
10
+ description "List the agents a workspace owns, oldest first, with the address each " \
11
+ "answers on. Read this before creating or changing one — it is how you " \
12
+ "learn which addresses are already taken."
13
+ params(
14
+ type: "object",
15
+ properties: {
16
+ workspace: {
17
+ type: "string",
18
+ description: "The workspace's username, the first half of /<workspace>/<agent>"
19
+ }
20
+ },
21
+ required: ["workspace"]
22
+ )
23
+
24
+ private
25
+
26
+ def run(args)
27
+ agents = anychat.workspace_agents(args["workspace"])
28
+ return "This workspace has no agents yet." if agents.empty?
29
+
30
+ agents.map { |agent| line(args["workspace"], agent) }.join("\n")
31
+ end
32
+
33
+ def line(workspace, agent)
34
+ parts = ["#{agent['display_name']} at /#{workspace}/#{agent['handle']}"]
35
+ parts << "— #{agent['description']}" if agent["description"].to_s.strip.length.positive?
36
+ parts << "(private)" unless agent["public"]
37
+ parts.join(" ")
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,67 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ask
4
+ module AnyChat
5
+ module MCP
6
+ module Tools
7
+ # What an existing agent becomes.
8
+ #
9
+ # The address being changed and the address being changed *to* are two
10
+ # different things, so they are two different arguments: `agent` says
11
+ # which one, `handle` says what to move it to. One name for both would
12
+ # be a sentence that cannot be read.
13
+ class UpdateAgent < Tool
14
+ tool_name "ask_anychat_update_agent"
15
+ description "Change an agent a workspace already owns. Only the arguments you pass " \
16
+ "are written — anything left out keeps its value. Pass handle to move " \
17
+ "the address it answers on."
18
+ params(
19
+ type: "object",
20
+ properties: {
21
+ workspace: {
22
+ type: "string",
23
+ description: "The workspace's username, the first half of /<workspace>/<agent>"
24
+ },
25
+ agent: {
26
+ type: "string",
27
+ description: "The address it answers on now, the second half of /<workspace>/<agent>"
28
+ },
29
+ display_name: {
30
+ type: "string",
31
+ description: "What the agent is called."
32
+ },
33
+ handle: {
34
+ type: "string",
35
+ description: "The address to move it to. A taken one is given the first free variant."
36
+ },
37
+ description: {
38
+ type: "string",
39
+ description: "One line about what this agent is for."
40
+ },
41
+ public: {
42
+ type: "boolean",
43
+ description: "Whether the world can find it."
44
+ }
45
+ },
46
+ required: %w[workspace agent]
47
+ )
48
+
49
+ private
50
+
51
+ def run(args)
52
+ attributes = writable(args, :display_name, :handle, :description, :public)
53
+ return nothing_to_change if attributes.empty?
54
+
55
+ agent = anychat.update_workspace_agent(args["workspace"], args["agent"], **attributes)
56
+
57
+ "Updated #{agent['display_name']} at #{agent['address']}."
58
+ end
59
+
60
+ def nothing_to_change
61
+ "Error: nothing to change. Pass at least one of display_name, handle, description, public."
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "tools/list_agents"
4
+ require_relative "tools/get_agent"
5
+ require_relative "tools/create_agent"
6
+ require_relative "tools/update_agent"
7
+ require_relative "tools/delete_agent"
8
+
9
+ module Ask
10
+ module AnyChat
11
+ module MCP
12
+ # Every tool this server exposes, in the order a model should reach for
13
+ # them: read, then write, then retire.
14
+ module Tools
15
+ ALL = [
16
+ ListAgents,
17
+ GetAgent,
18
+ CreateAgent,
19
+ UpdateAgent,
20
+ DeleteAgent
21
+ ].freeze
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ask
4
+ module AnyChat
5
+ module MCP
6
+ VERSION = "0.1.1"
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "ask/mcp"
4
+ require "ask-anychat"
5
+ require_relative "mcp/version"
6
+ require_relative "mcp/tool"
7
+ require_relative "mcp/tools"
8
+
9
+ module Ask
10
+ module AnyChat
11
+ # MCP (Model Context Protocol) server for Anychat.
12
+ #
13
+ # Exposes workspace agent CRUD over MCP, so a client that speaks the
14
+ # protocol can create and manage a workspace's agents without knowing
15
+ # anything about this API. Tool names are prefixed `ask_anychat_` to keep
16
+ # them from colliding with a client's own tools of the same name.
17
+ module MCP
18
+ # Every tool, each holding the client it was given — or building one from
19
+ # the environment on first use, which is what the executable relies on.
20
+ def self.tools(client: nil)
21
+ Tools::ALL.map { |tool| tool.new(client: client) }
22
+ end
23
+
24
+ # Serve over stdio. Blocking — the last line of an entry-point script.
25
+ #
26
+ # $ ask-anychat-mcp
27
+ #
28
+ # Register it with an MCP client by command; set ANYCHAT_TOKEN and, if it
29
+ # is not the hosted app, ANYCHAT_BASE_URL in the server's environment.
30
+ def self.start(client: nil)
31
+ Ask::MCP::Server.start_stdio(
32
+ name: "ask-anychat-mcp",
33
+ version: VERSION,
34
+ tools: tools(client: client),
35
+ capabilities: { tools: {} },
36
+ debug: ENV["DEBUG"] == "1"
37
+ )
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "ask/anychat/mcp"
metadata ADDED
@@ -0,0 +1,119 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ask-anychat-mcp
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - Kaka Ruto
8
+ bindir: bin
9
+ cert_chain: []
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: ask-anychat
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - ">="
17
+ - !ruby/object:Gem::Version
18
+ version: 0.1.0
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - ">="
24
+ - !ruby/object:Gem::Version
25
+ version: 0.1.0
26
+ - !ruby/object:Gem::Dependency
27
+ name: ask-mcp
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 0.5.0
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: 0.5.0
40
+ - !ruby/object:Gem::Dependency
41
+ name: minitest
42
+ requirement: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: '5.25'
47
+ type: :development
48
+ prerelease: false
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: '5.25'
54
+ - !ruby/object:Gem::Dependency
55
+ name: rake
56
+ requirement: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: '13.0'
61
+ type: :development
62
+ prerelease: false
63
+ version_requirements: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: '13.0'
68
+ description: A minimal MCP (Model Context Protocol) server that exposes the agents
69
+ an Anychat workspace owns as callable tools over stdio — list them, read one, bring
70
+ a new one into being, change one, or retire one. Designed for clients that speak
71
+ MCP (ZCode, Claude Code, and the like). The tool shell (name, schema, call) lives
72
+ here, wrapping ask-anychat; the API client itself is that gem's.
73
+ email:
74
+ - kaka@myrrlabs.com
75
+ executables:
76
+ - ask-anychat-mcp
77
+ extensions: []
78
+ extra_rdoc_files: []
79
+ files:
80
+ - CHANGELOG.md
81
+ - LICENSE
82
+ - README.md
83
+ - bin/ask-anychat-mcp
84
+ - lib/ask-anychat-mcp.rb
85
+ - lib/ask/anychat/mcp.rb
86
+ - lib/ask/anychat/mcp/tool.rb
87
+ - lib/ask/anychat/mcp/tools.rb
88
+ - lib/ask/anychat/mcp/tools/create_agent.rb
89
+ - lib/ask/anychat/mcp/tools/delete_agent.rb
90
+ - lib/ask/anychat/mcp/tools/get_agent.rb
91
+ - lib/ask/anychat/mcp/tools/list_agents.rb
92
+ - lib/ask/anychat/mcp/tools/update_agent.rb
93
+ - lib/ask/anychat/mcp/version.rb
94
+ homepage: https://github.com/ask-rb/ask-anychat-mcp
95
+ licenses:
96
+ - MIT
97
+ metadata:
98
+ homepage_uri: https://github.com/ask-rb/ask-anychat-mcp
99
+ source_code_uri: https://github.com/ask-rb/ask-anychat-mcp
100
+ changelog_uri: https://github.com/ask-rb/ask-anychat-mcp/blob/master/CHANGELOG.md
101
+ rubygems_mfa_required: 'true'
102
+ rdoc_options: []
103
+ require_paths:
104
+ - lib
105
+ required_ruby_version: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ version: '3.2'
110
+ required_rubygems_version: !ruby/object:Gem::Requirement
111
+ requirements:
112
+ - - ">="
113
+ - !ruby/object:Gem::Version
114
+ version: '0'
115
+ requirements: []
116
+ rubygems_version: 4.0.18
117
+ specification_version: 4
118
+ summary: MCP server for Anychat
119
+ test_files: []