Skip to content

Forward region via meta#71

Merged
kyoncal merged 9 commits into
aws:mainfrom
kyoncal:forward-region-via-meta
Nov 11, 2025
Merged

Forward region via meta#71
kyoncal merged 9 commits into
aws:mainfrom
kyoncal:forward-region-via-meta

Conversation

@kyoncal

@kyoncal kyoncal commented Nov 4, 2025

Copy link
Copy Markdown
Contributor

Extension of #62

Summary

Implemented automatic AWS_REGION metadata injection into MCP JSON-RPC requests using httpx request hooks. Added _inject_metadata_hook function to hooks.py that injects metadata into the _meta field of request params, merging with existing metadata when present (existing values take precedence). Added optional metadata argument. Includes unit tests and an end-to-end integration test with a new echo_metadata tool in the test MCP server to verify metadata transmission.

User experience

AWS_REGION is now automatically injected into all MCP requests transparently - no manual configuration required. The proxy adds region information to the _meta field, making it available to MCP servers without any client-side code changes.

Checklist

If your change doesn't seem to apply, please leave them unchecked.

  • I have reviewed the contributing guidelines
  • I have performed a self-review of this change
  • Changes have been tested
  • Changes are documented

Is this a breaking change? (Y/N)

  • Yes
  • No

Please add details about how this change was tested.

  • Did integration tests succeed?
  • If the feature is a new use case, is it necessary to add a new integration test case?

Acknowledgment

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

@kyoncal kyoncal force-pushed the forward-region-via-meta branch from c3909e2 to aa52f01 Compare November 4, 2025 17:01
Comment thread mcp_proxy_for_aws/cli.py
Comment thread mcp_proxy_for_aws/sigv4_helper.py Outdated
Comment thread mcp_proxy_for_aws/sigv4_helper.py Outdated
event_hooks={'response': [_handle_error_response]},
event_hooks={
'response': [_handle_error_response],
'request': [partial(_inject_metadata_hook, metadata or {}, region, service)],

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

per the mcp spec, the _meta field is https://modelcontextprotocol.io/specification/2025-06-18/basic/index#meta

Should we communicate with the teams owning remote MCP that we will use their endpoint as the key in meta? The resulted meta field would look like:

{
    "params": {
        "_meta": {
            "some-mcp-server.us-east-1.amazonaws.com/config": {
                "key": "value",
                "from": "cli-args"
            }
        }
    }
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using their endpoint as a key could be an idea for the future, however, I don't see it adding much value right, especially since there is currently only one metadata field that we set.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Optionally, our cli program can take an argument --config-key as the key in _meta.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, the prefix is optional. But then the config key needs to be chosen carefully.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To my knowledge, the only thing that matters with regard to naming is that these rules are followed and that the user doesn't break them:

Prefix:

If specified, MUST be a series of labels separated by dots (.), followed by a slash (/).
    Labels MUST start with a letter and end with a letter or digit; interior characters can be letters, digits, or hyphens (-).
Any prefix beginning with zero or more valid labels, followed by modelcontextprotocol or mcp, followed by any valid label, is reserved for MCP use.
    For example: modelcontextprotocol.io/, mcp.dev/, api.modelcontextprotocol.org/, and tools.mcp.com/ are all reserved.

Name:

Unless empty, MUST begin and end with an alphanumeric character ([a-z0-9A-Z]).
MAY contain hyphens (-), underscores (_), dots (.), and alphanumerics in between.

Perhaps we can add some sort of sanitation? Changing the spec that other people expect at this point might not be optimal

@kyoncal kyoncal force-pushed the forward-region-via-meta branch 4 times, most recently from 4d50207 to 8158ecf Compare November 5, 2025 13:50
@kyoncal kyoncal marked this pull request as ready for review November 5, 2025 14:00
@kyoncal kyoncal requested a review from a team as a code owner November 5, 2025 14:00
@kyoncal kyoncal requested review from anasstahr and wzxxing November 5, 2025 14:00
@kyoncal kyoncal marked this pull request as draft November 5, 2025 14:09
@kyoncal kyoncal force-pushed the forward-region-via-meta branch from 8158ecf to 4ffb75d Compare November 6, 2025 14:47
logger.debug('Using region: %s', region)

# Build metadata dictionary - start with AWS_REGION, then merge user metadata
metadata = {'AWS_REGION': region}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason why we are always setting this metadata?

I'm just wondering if we shouldn't set nothing in the default case, and users must specify the param if they want to use this

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From my understanding of the intended workflow, there is no variation wherein an AWS_REGION is not necessary. If this is not the case, I'm happy to make it entirely optional.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's maybe differentiate between "feature-request" and "how other projects will use it". The "feature-request" here is to add the ability to add metadata.

With that in mind, I think let's make it completely optional

Comment thread mcp_proxy_for_aws/server.py Outdated
@kyoncal kyoncal force-pushed the forward-region-via-meta branch from d70f559 to 2ad1d4d Compare November 7, 2025 15:40
@kyoncal kyoncal marked this pull request as ready for review November 10, 2025 10:43
Comment thread tests/unit/test_hooks.py
Comment thread mcp_proxy_for_aws/hooks.py Outdated
…igv4_helper.py

This refactor was needed in order to avoid a circular depdency, which resulted in a mid-module import.

@arangatang arangatang left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did like the hooks seperation, maybe we can reshuffle again later without the circular dep. For now this looks ok. Thanks for the work @kyoncal!

@kyoncal kyoncal merged commit 0b2e3a7 into aws:main Nov 11, 2025
3 checks passed
wzxxing pushed a commit to wzxxing/mcp-proxy-for-aws that referenced this pull request Nov 11, 2025
* feat(sigv4_helper): inject AWS_REGION in _meta

* Override the sigv4 signature when adding _meta.

* feat(sigv4_helper): add region and service argument to _inject_metadata_hook to allow for proper resigning of sigv4 to work

* feat(server.py): add forwarding region as optional argument

* feat: replace forwarding region with metadata forwarding

* refactor: move the hooks from sigv4_helper.py into a new folder and add tests

* refactor(siv4_helper.py): move signing logic from client creation to an event hook

* test(test_hooks.py): add assertions

* refactor(sigv4_helper.py): remove hooks.py module and move hooks to sigv4_helper.py

This refactor was needed in order to avoid a circular depdency, which resulted in a mid-module import.

---------

Co-authored-by: Kyon Caldera <kyonc@amazon.com>
Co-authored-by: Leonardo Araneda Freccero <araneda@amazon.com>
harv-aws pushed a commit to harv-aws/mcp-proxy-for-aws that referenced this pull request Nov 11, 2025
* feat(sigv4_helper): inject AWS_REGION in _meta

* Override the sigv4 signature when adding _meta.

* feat(sigv4_helper): add region and service argument to _inject_metadata_hook to allow for proper resigning of sigv4 to work

* feat(server.py): add forwarding region as optional argument

* feat: replace forwarding region with metadata forwarding

* refactor: move the hooks from sigv4_helper.py into a new folder and add tests

* refactor(siv4_helper.py): move signing logic from client creation to an event hook

* test(test_hooks.py): add assertions

* refactor(sigv4_helper.py): remove hooks.py module and move hooks to sigv4_helper.py

This refactor was needed in order to avoid a circular depdency, which resulted in a mid-module import.

---------

Co-authored-by: Kyon Caldera <kyonc@amazon.com>
Co-authored-by: Leonardo Araneda Freccero <araneda@amazon.com>
arangatang added a commit that referenced this pull request Nov 13, 2025
* pypi release automation through github actions

* Forward region via meta (#71)

* feat(sigv4_helper): inject AWS_REGION in _meta

* Override the sigv4 signature when adding _meta.

* feat(sigv4_helper): add region and service argument to _inject_metadata_hook to allow for proper resigning of sigv4 to work

* feat(server.py): add forwarding region as optional argument

* feat: replace forwarding region with metadata forwarding

* refactor: move the hooks from sigv4_helper.py into a new folder and add tests

* refactor(siv4_helper.py): move signing logic from client creation to an event hook

* test(test_hooks.py): add assertions

* refactor(sigv4_helper.py): remove hooks.py module and move hooks to sigv4_helper.py

This refactor was needed in order to avoid a circular depdency, which resulted in a mid-module import.

---------

Co-authored-by: Kyon Caldera <kyonc@amazon.com>
Co-authored-by: Leonardo Araneda Freccero <araneda@amazon.com>

* docs: mention creating issues first before sending large PR with new feature (#76)

* feat: allow iam mcp client to take a botocore credentials object (#84)

* pypi release automation through github actions

* chore: pypi publishing added to development.md

* chore: simplifying uv install

* fix: adding input commit id for integ tests, and passing it in publish workflows.

---------

Co-authored-by: Harvish N S <harvishn@amazon.com>
Co-authored-by: Kyon <91875365+kyoncal@users.noreply.github.com>
Co-authored-by: Kyon Caldera <kyonc@amazon.com>
Co-authored-by: Leonardo Araneda Freccero <araneda@amazon.com>
Co-authored-by: wzxxing <169175349+wzxxing@users.noreply.github.com>
Co-authored-by: Leonardo Araneda Freccero <arangatang@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants