diff --git entity.api.php entity.api.php
index affda7c..aff578d 100644
--- entity.api.php
+++ entity.api.php
@@ -120,6 +120,9 @@
  *   entity_metadata_no_hook_node_access() for an example.
  *   This is optional, but suggested for the Rules integration, and required for
  *   the admin ui (see above).
+ * - form callback: (optional) Specfiy a callback that returns a fully built
+ *   edit form for your entity type. See entity_form().
+ *   In case the 'admin ui' is used, no callback needs to be specified.
  *
  * @see hook_entity_info()
  * @see entity_metadata_hook_entity_info()
@@ -173,6 +176,8 @@ function entity_crud_hook_entity_info() {
  *   entity of this type.
  * - view callback: (optional) A callback to render a list of entities.
  *   See entity_metadata_view_node() as example.
+ * - form callback: (optional) A callback that returns a fully built edit form
+ *   for the entity type.
  * - token type: (optional) A type name to use for token replacements. Set it
  *   to FALSE if there aren't any token replacements for this entity type.
  *
@@ -182,6 +187,8 @@ function entity_crud_hook_entity_info() {
  * @see entity_create()
  * @see entity_save()
  * @see entity_delete()
+ * @see entity_view()
+ * @see entity_form()
  */
 function entity_metadata_hook_entity_info() {
   return array(
diff --git entity.module entity.module
index 7ec5f13..09ce5a6 100644
--- entity.module
+++ entity.module
@@ -54,7 +54,7 @@ define('ENTITY_FIXED', 0x04 | 0x02);
  * @param $entity_type
  *   The type of the entity.
  * @param $op
- *   One of 'create', 'view', 'save', 'delete' or 'access.
+ *   One of 'create', 'view', 'save', 'delete', 'access' or 'form'.
  */
 function entity_type_supports($entity_type, $op) {
   $info = entity_get_info($entity_type);
@@ -64,8 +64,15 @@ function entity_type_supports($entity_type, $op) {
     'delete' => 'deletion callback',
     'save' => 'save callback',
     'access' => 'access callback',
+    'form' => 'form callback'
   );
-  if (isset($info[$keys[$op]]) || ($op != 'access' && in_array('EntityAPIControllerInterface', class_implements($info['controller class'])))) {
+  if (isset($info[$keys[$op]])) {
+    return TRUE;
+  }
+  if ($op != 'access' && in_array('EntityAPIControllerInterface', class_implements($info['controller class']))) {
+    return TRUE;
+  }
+  if ($op == 'form' && entity_ui_controller($entity_type)) {
     return TRUE;
   }
 }
@@ -411,6 +418,38 @@ function entity_access($op, $entity_type, $entity = NULL, $account = NULL) {
 }
 
 /**
+ * Gets the edit form for any entity.
+ *
+ * This helper makes use of drupal_get_form() and the regular form builder
+ * function of the entity type to retrieve and process the form as usual.
+ *
+ * In order to use this helper to show an entity add form, the new entity object
+ * can be created via entity_create() or entity_property_values_create_entity().
+ *
+ * @param $entity_type
+ *   The type of the entity.
+ * @param $entity
+ *   The entity to show the edit form for.
+ * @return
+ *   The renderable array of the form. If there is no entity form or missing
+ *   metadata, FALSE is returned.
+ *
+ * @see entity_type_supports()
+ */
+function entity_form($entity_type, $entity) {
+  $info = entity_get_info($entity_type);
+  if (isset($info['form callback'])) {
+    return $info['form callback']($entity, $entity_type);
+  }
+  // If there is an UI controller, the providing module has to implement the
+  // entity form using entity_ui_get_form().
+  elseif (entity_ui_controller($entity_type)) {
+    return entity_metadata_form_entity_ui($entity, $entity_type);
+  }
+  return FALSE;
+}
+
+/**
  * Converts an array of entities to be keyed by the values of a given property.
  *
  * @param array $entities
@@ -924,7 +963,7 @@ function entity_forms($form_id, $args) {
 }
 
 /**
- * Gets an entity form.
+ * A wrapper around drupal_get_form() that helps building entity forms.
  *
  * This function may be used by entities to build their entity form. It has to
  * be used instead of calling drupal_get_form().
@@ -945,7 +984,10 @@ function entity_forms($form_id, $args) {
  *   initialized with empty values using entity_create(). Thus entities, for
  *   which this is problematic have to care to pass in an initialized entity.
  * @param $op
- *   One of 'edit', 'add' or 'clone'. Defaults to edit.
+ *   (optional) One of 'edit', 'add' or 'clone'. Defaults to edit.
+ * @param $form_state
+ *   (optional) A pre-populated form state, e.g. to add in form include files.
+ *   See entity_metadata_form_entity_ui().
  *
  * @return
  *   The fully built and processed form, ready to be rendered.
@@ -953,7 +995,7 @@ function entity_forms($form_id, $args) {
  * @see EntityDefaultUIController::hook_forms()
  * @see entity_ui_form_submit_build_entity()
  */
-function entity_ui_get_form($entity_type, $entity, $op = 'edit') {
+function entity_ui_get_form($entity_type, $entity, $op = 'edit', $form_state = array()) {
   if (isset($entity)) {
     list(, , $bundle) = entity_extract_ids($entity_type, $entity);
   }
@@ -973,7 +1015,7 @@ function entity_ui_get_form($entity_type, $entity, $op = 'edit') {
   // which the module implementing the form constructor may safely ignore.
   // @see entity_forms()
   $form_state['build_info']['args'] = array($entity, $op, $entity_type);
-  module_load_include('inc', 'entity', 'includes/entity.ui');
+  form_load_include($form_state, 'inc', 'entity', 'includes/entity.ui');
   return drupal_build_form($form_id, $form_state);
 }
 
@@ -1105,6 +1147,10 @@ function _entity_info_add_metadata_callbacks(&$entity_info) {
   $entity_info['file']['save callback'] = 'file_save';
   $entity_info['file']['deletion callback'] = 'entity_metadata_delete_file';
 
+  // Form callbacks.
+  $entity_info['node']['form callback'] = 'entity_metadata_form_node';
+  $entity_info['user']['form callback'] = 'entity_metadata_form_user';
+
   // View callbacks.
   $entity_info['node']['view callback'] = 'entity_metadata_view_node';
   $entity_info['user']['view callback'] = 'entity_metadata_view_single';
@@ -1115,6 +1161,7 @@ function _entity_info_add_metadata_callbacks(&$entity_info) {
     $entity_info['comment']['save callback'] = 'comment_save';
     $entity_info['comment']['deletion callback'] = 'comment_delete';
     $entity_info['comment']['view callback'] = 'entity_metadata_view_comment';
+    $entity_info['comment']['form callback'] = 'entity_metadata_form_comment';
   }
   if (module_exists('taxonomy')) {
     $entity_info['taxonomy_term']['access callback'] = 'entity_metadata_taxonomy_access';
@@ -1122,11 +1169,13 @@ function _entity_info_add_metadata_callbacks(&$entity_info) {
     $entity_info['taxonomy_term']['save callback'] = 'taxonomy_term_save';
     $entity_info['taxonomy_term']['deletion callback'] = 'taxonomy_term_delete';
     $entity_info['taxonomy_term']['view callback'] = 'entity_metadata_view_single';
+    $entity_info['taxonomy_term']['form callback'] = 'entity_metadata_form_taxonomy_term';
 
     $entity_info['taxonomy_vocabulary']['access callback'] = 'entity_metadata_taxonomy_access';
     $entity_info['taxonomy_vocabulary']['creation callback'] = 'entity_metadata_create_object';
     $entity_info['taxonomy_vocabulary']['save callback'] = 'taxonomy_vocabulary_save';
     $entity_info['taxonomy_vocabulary']['deletion callback'] = 'taxonomy_vocabulary_delete';
+    $entity_info['taxonomy_vocabulary']['form callback'] = 'entity_metadata_form_taxonomy_vocabulary';
     // Token type mapping.
     $entity_info['taxonomy_term']['token type'] = 'term';
     $entity_info['taxonomy_vocabulary']['token type'] = 'vocabulary';
diff --git modules/callbacks.inc modules/callbacks.inc
index aac7c2e..914d4a8 100644
--- modules/callbacks.inc
+++ modules/callbacks.inc
@@ -730,6 +730,76 @@ function entity_metadata_view_single($entities, $view_mode = 'full', $langcode =
 }
 
 /**
+ * Callback to get the form of a node.
+ */
+function entity_metadata_form_node($node) {
+  // Pre-populate the form-state with the right form include.
+  $form_state['build_info']['args'] = array($node);
+  form_load_include($form_state, 'inc', 'node', 'node.pages');
+  return drupal_build_form($node->type . '_node_form', $form_state);
+}
+
+/**
+ * Callback to get the form of a comment.
+ */
+function entity_metadata_form_comment($comment) {
+  if (!isset($comment->node_type)) {
+    $node = node_load($comment->nid);
+    $comment->node_type = 'comment_node_' . $node->type;
+  }
+  return drupal_get_form($comment->node_type . '_form', $comment);
+}
+
+/**
+ * Callback to get the form of a user account.
+ */
+function entity_metadata_form_user($account) {
+  // Pre-populate the form-state with the right form include.
+  $form_state['build_info']['args'] = array($account);
+  form_load_include($form_state, 'inc', 'user', 'user.pages');
+  return drupal_build_form('user_profile_form', $form_state);
+}
+
+/**
+ * Callback to get the form of a term.
+ */
+function entity_metadata_form_taxonomy_term($term) {
+  // Pre-populate the form-state with the right form include.
+  $form_state['build_info']['args'] = array($term);
+  form_load_include($form_state, 'inc', 'taxonomy', 'taxonomy.admin');
+  return drupal_build_form('taxonomy_form_term', $form_state);
+}
+
+/**
+ * Callback to get the form of a vocabulary.
+ */
+function entity_metadata_form_taxonomy_vocabulary($term) {
+  // Pre-populate the form-state with the right form include.
+  $form_state['build_info']['args'] = array($term);
+  form_load_include($form_state, 'inc', 'taxonomy', 'taxonomy.admin');
+  return drupal_build_form('taxonomy_form_term', $form_state);
+}
+
+/**
+ * Callback to get the form for entities using the entity API admin ui.
+ */
+function entity_metadata_form_entity_ui($entity, $entity_type) {
+  $info = entity_get_info($entity_type);
+  $form_state = array();
+  // Add in the include file as the form API does else with the include file
+  // specified for the active menu item.
+  if (!empty($info['admin ui']['file'])) {
+    $path = isset($info['admin ui']['file path']) ? $info['admin ui']['file path'] : drupal_get_path('module', $info['module']);
+    $form_state['build_info']['files']['entity_ui'] = $path . '/' . $info['admin ui']['file'];
+    // Also load the include file.
+    if (file_exists($form_state['build_info']['files']['entity_ui'])) {
+      require_once DRUPAL_ROOT . '/' . $form_state['build_info']['files']['entity_ui'];
+    }
+  }
+  return entity_ui_get_form($entity_type, $entity, $op = 'edit', $form_state);
+}
+
+/**
  * Callback for querying entity properties having their values stored in the
  * entities main db table.
  */
